From ffd47e9af73a9e4a27e1747589085bd2b9f9557a Mon Sep 17 00:00:00 2001 From: Rocco Marco Guglielmi Date: Wed, 1 Jun 2016 15:40:44 +0000 Subject: Extended PLLSAI support. Added clock 48 selector. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9553 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/ports/STM32/STM32F4xx/hal_lld.c | 49 ++++++- os/hal/ports/STM32/STM32F4xx/hal_lld.h | 237 ++++++++++++++++++++++++++++++--- 2 files changed, 260 insertions(+), 26 deletions(-) (limited to 'os/hal/ports') diff --git a/os/hal/ports/STM32/STM32F4xx/hal_lld.c b/os/hal/ports/STM32/STM32F4xx/hal_lld.c index aa38fb39e..91583f263 100644 --- a/os/hal/ports/STM32/STM32F4xx/hal_lld.c +++ b/os/hal/ports/STM32/STM32F4xx/hal_lld.c @@ -176,7 +176,7 @@ void stm32_clock_init(void) { /* 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) @@ -223,7 +223,7 @@ void stm32_clock_init(void) { /* Waiting for PLL lock.*/ while (!(RCC->CR & RCC_CR_PLLRDY)) ; -#endif /* STM32_OVERDRIVE_REQUIRED */ +#endif /* STM32_ACTIVATE_PLL */ #if STM32_ACTIVATE_PLLI2S /* PLLI2S activation.*/ @@ -234,24 +234,61 @@ void stm32_clock_init(void) { /* Waiting for PLL lock.*/ while (!(RCC->CR & RCC_CR_PLLI2SRDY)) ; -#endif +#endif /* STM32_ACTIVATE_PLLI2S */ #if STM32_ACTIVATE_PLLSAI /* PLLSAI activation.*/ - RCC->PLLSAICFGR = STM32_PLLSAIN | STM32_PLLSAIR | STM32_PLLSAIQ; - RCC->DCKCFGR = (RCC->DCKCFGR & ~RCC_DCKCFGR_PLLSAIDIVR) | STM32_PLLSAIR_POST; + RCC->PLLSAICFGR = STM32_PLLSAIN | STM32_PLLSAIR | STM32_PLLSAIQ | + STM32_PLLSAIP; + RCC->CR |= RCC_CR_PLLSAION; /* Waiting for PLL lock.*/ while (!(RCC->CR & RCC_CR_PLLSAIRDY)) ; -#endif +#endif /* STM32_ACTIVATE_PLLSAI */ /* Other clock-related settings (dividers, MCO etc).*/ RCC->CFGR = STM32_MCO2PRE | STM32_MCO2SEL | STM32_MCO1PRE | STM32_MCO1SEL | STM32_I2SSRC | STM32_RTCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; +#if defined(STM32F446xx) + /* 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_PLLSAIDIVR != STM32_PLLSAIDIVR_OFF + dckcfgr |= STM32_PLLSAIDIVR; +#endif + RCC->DCKCFGR = dckcfgr | STM32_PLLI2SDIVQ | STM32_PLLSAIDIVQ; + } + RCC->DCKCFGR2 = STM32_CK48MSEL; +#elif defined(STM32F469xx) || defined(STM32F479xx) + /* 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_PLLSAIDIVR != STM32_PLLSAIDIVR_OFF + dckcfgr |= STM32_PLLSAIDIVR; + #endif + RCC->DCKCFGR = dckcfgr | STM32_PLLI2SDIVQ | STM32_PLLSAIDIVQ | + STM32_CK48MSEL; + } +#endif + /* Flash setup.*/ #if !defined(STM32_REMOVE_REVISION_A_FIX) /* Some old revisions of F4x MCUs randomly crashes with compiler diff --git a/os/hal/ports/STM32/STM32F4xx/hal_lld.h b/os/hal/ports/STM32/STM32F4xx/hal_lld.h index b68968975..925dda77a 100644 --- a/os/hal/ports/STM32/STM32F4xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32F4xx/hal_lld.h @@ -52,7 +52,7 @@ /** * @brief Defines the support for realtime counters in the HAL. */ -#define HAL_IMPLEMENTS_COUNTERS TRUE +#define HAL_IMPLEMENTS_COUNTERS TRUE /** * @name Platform identification macros @@ -200,6 +200,16 @@ */ #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. */ @@ -311,6 +321,8 @@ #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 @@ -450,10 +462,10 @@ #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) /**< PLL clock divided by 2. */ -#define STM32_PLLI2SP_DIV4 (1 << 16) /**< PLL clock divided by 4. */ -#define STM32_PLLI2SP_DIV6 (2 << 16) /**< PLL clock divided by 6. */ -#define STM32_PLLI2SP_DIV8 (3 << 16) /**< PLL clock divided by 8. */ +#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_PLLI2SQ_MASK (15 << 24) /**< PLLI2SQ mask. */ #define STM32_PLLI2SR_MASK (7 << 28) /**< PLLI2SR mask. */ /** @} */ @@ -465,6 +477,10 @@ #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. */ /** @} */ @@ -484,7 +500,7 @@ * @name RCC_DCKCFGR register bits definitions * @{ */ -#define STM32_PLLI2SDIVQ_MASK (31 << 0) /**< PLLSAIDIVQ mask. */ +#define STM32_PLLI2SDIVQ_MASK (31 << 0) /**< PLLI2SDIVQ mask. */ #define STM32_PLLSAIDIVQ_MASK (31 << 8) /**< PLLSAIDIVQ mask. */ @@ -496,14 +512,14 @@ #define STM32_PLLSAIDIVR_OFF 0xFFFFFFFFU /**< LCD CLK is not required. */ #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_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_SAIPLL (0 << 22) /**< SAI2 source is SAIPLL. */ -#define STM32_SAI2SEL_I2SPLL (1 << 22) /**< SAI2 source is I2SPLL. */ +#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.*/ @@ -795,6 +811,13 @@ #define STM32_PLLI2SQ_VALUE 4 #endif +/** + * @brief STM32_PLLI2SDIVQ divider value (SAI clock divider). + */ +#if !defined(STM32_PLLI2SDIVQ) || defined(__DOXYGEN__) +#define STM32_PLLI2SDIVQ 0 +#endif + /** * @brief PLLSAIM value. * @note The allowed values are 2..63. @@ -839,6 +862,41 @@ #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 PLLSAIDIVR divider value (LCD clock divider). + */ +#if !defined(STM32_PLLSAIDIVQ) || defined(__DOXYGEN__) +#define STM32_PLLSAIDIVQ 0 +#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 PLL48CLK clock source. + */ +#if !defined(STM32_CK48MSEL) || defined(__DOXYGEN__) +#define STM32_CK48MSEL STM32_CK48MSEL_PLL +#endif + /** * @brief AHB prescaler value. */ @@ -1140,6 +1198,17 @@ #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 */ /* @@ -1480,7 +1549,10 @@ /* * PLLI2S enable check. */ -#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) || defined(__DOXYGEN__) +#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLLI2S) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLI2S) || \ + defined(__DOXYGEN__) /** * @brief PLLI2S activation flag. */ @@ -1574,10 +1646,49 @@ #endif #endif /* defined(STM32F446xx) */ +/** + * @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_CLOCK48_REQUIRED && (STM32_CK48MSEL == STM32_CK48MSEL_PLLSAI)) | \ + (STM32_PLLSAIDIVR != STM32_PLLSAIDIVR_OFF) || \ + (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI) || \ + (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI) || \ + defined(__DOXYGEN__) /** * @brief PLLSAI activation flag. */ +#define STM32_ACTIVATE_PLLSAI TRUE +#else #define STM32_ACTIVATE_PLLSAI FALSE +#endif /** * @brief STM32_PLLSAIN field. @@ -1610,34 +1721,89 @@ #endif /** - * @brief PLLI2S VCO frequency. + * @brief STM32_PLLSAIP field. */ -#define STM32_PLLI2SVCO (STM32_PLLI2SCLKIN * STM32_PLLI2SN_VALUE) + +#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) /* - * PLLI2S VCO frequency range check. + * PLLSAI 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)" +#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 PLLI2S output clock frequency. + * @brief PLLSAI P output clock frequency. */ -#define STM32_PLLI2SCLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SR_VALUE) +#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 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 @@ -1647,14 +1813,19 @@ */ #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 @@ -1664,12 +1835,16 @@ */ #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 @@ -1679,14 +1854,19 @@ */ #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 @@ -1716,12 +1896,16 @@ */ #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 @@ -1730,10 +1914,23 @@ * @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) +#if (STM32_PLL48CLK != 48000000) +#error "STM32_PLL48CLK wrong value" +#endif +#elif STM32_CK48MSEL == STM32_CK48MSEL_PLLSAI +#define STM32_PLL48CLK (STM32_PLLSAIVCO / STM32_PLLSAIQ_VALUE) +#if (STM32_PLL48CLK != 48000000) +#error "STM32_PLL48CLK wrong value" +#endif #else -#define STM32_PLL48CLK 0 +#error "invalid source selected for PLL48CLK clock" #endif +#else /* !STM32_CLOCK48_REQUIRED */ +#define STM32_PLL48CLK 0 +#endif /* !STM32_CLOCK48_REQUIRED */ + /** * @brief Clock of timers connected to APB1 -- cgit v1.2.3