HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *pRCC_OscInitStruct) { uint32_t tickstart; HAL_StatusTypeDef status; uint32_t sysclk_source; uint32_t pll_config; FlagStatus pwrboosten = RESET; uint32_t temp1_pllckcfg; uint32_t temp2_pllckcfg; /* Check Null pointer */ if (pRCC_OscInitStruct == NULL) { return HAL_ERROR; } /* Check the parameters */ assert_param(IS_RCC_OSCILLATORTYPE(pRCC_OscInitStruct->OscillatorType)); sysclk_source = __HAL_RCC_GET_SYSCLK_SOURCE(); pll_config = __HAL_RCC_GET_PLL_OSCSOURCE(); /*----------------------------- MSI Configuration --------------------------*/ if (((pRCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI) { /* Check the parameters */ assert_param(IS_RCC_MSI(pRCC_OscInitStruct->MSIState)); assert_param(IS_RCC_MSICALIBRATION_VALUE(pRCC_OscInitStruct->MSICalibrationValue)); assert_param(IS_RCC_MSI_CLOCK_RANGE(pRCC_OscInitStruct->MSIClockRange)); /*Check if MSI is used as system clock or as PLL source when PLL is selected as system clock*/ if ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_MSI) || ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (pll_config == RCC_PLLSOURCE_MSI))) { if ((READ_BIT(RCC->CR, RCC_CR_MSISRDY) != 0U) && (pRCC_OscInitStruct->MSIState == RCC_MSI_OFF)) { return HAL_ERROR; } /* Otherwise, just the calibration and MSI range change are allowed */ else { /* To correctly read data from FLASH memory, the number of wait states (LATENCY) must be correctly programmed according to the frequency of the CPU clock (HCLK) and the supply voltage of the device */ if (pRCC_OscInitStruct->MSIClockRange > __HAL_RCC_GET_MSI_RANGE()) { /* Decrease number of wait states update if necessary */ /* Only possible when MSI is the System clock source */ if (sysclk_source == RCC_SYSCLKSOURCE_STATUS_MSI) { if (RCC_SetFlashLatencyFromMSIRange(pRCC_OscInitStruct->MSIClockRange) != HAL_OK) { return HAL_ERROR; } } /* Selects the Multiple Speed oscillator (MSI) clock range */ __HAL_RCC_MSI_RANGE_CONFIG(pRCC_OscInitStruct->MSIClockRange); /* Adjusts the Multiple Speed oscillator (MSI) calibration value */ __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST((pRCC_OscInitStruct->MSICalibrationValue), \ (pRCC_OscInitStruct->MSIClockRange)); } else { /* Else, keep current flash latency while decreasing applies */ /* Selects the Multiple Speed oscillator (MSI) clock range */ __HAL_RCC_MSI_RANGE_CONFIG(pRCC_OscInitStruct->MSIClockRange); /* Adjusts the Multiple Speed oscillator (MSI) calibration value */ __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST((pRCC_OscInitStruct->MSICalibrationValue), \ (pRCC_OscInitStruct->MSIClockRange)); if (sysclk_source == RCC_SYSCLKSOURCE_STATUS_MSI) { if (RCC_SetFlashLatencyFromMSIRange(pRCC_OscInitStruct->MSIClockRange) != HAL_OK) { return HAL_ERROR; } } } /* Update the SystemCoreClock global variable */ (void) HAL_RCC_GetHCLKFreq(); /* Configure the source of time base considering new system clocks settings*/ status = HAL_InitTick(uwTickPrio); if (status != HAL_OK) { return status; } } } else { /* Check the MSI State */ if (pRCC_OscInitStruct->MSIState != RCC_MSI_OFF) { /* Enable the Internal High Speed oscillator (MSI) */ __HAL_RCC_MSI_ENABLE(); tickstart = HAL_GetTick(); /* Wait till MSI is ready */ while (READ_BIT(RCC->CR, RCC_CR_MSISRDY) == 0U) { if ((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } /* Selects the Multiple Speed oscillator (MSI) clock range */ __HAL_RCC_MSI_RANGE_CONFIG(pRCC_OscInitStruct->MSIClockRange); /* Adjusts the Multiple Speed oscillator (MSI) calibration value */ __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST((pRCC_OscInitStruct->MSICalibrationValue), \ (pRCC_OscInitStruct->MSIClockRange)); } else { /* Disable the Internal High Speed oscillator (MSI) */ __HAL_RCC_MSI_DISABLE(); tickstart = HAL_GetTick(); /* Wait till MSI is ready */ while (READ_BIT(RCC->CR, RCC_CR_MSISRDY) != 0U) { if ((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } } } /*------------------------------- HSE Configuration ------------------------*/ if (((pRCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE) { /* Check the parameters */ assert_param(IS_RCC_HSE(pRCC_OscInitStruct->HSEState)); /* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */ if ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_HSE) || ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (pll_config == RCC_PLLSOURCE_HSE))) { if ((READ_BIT(RCC->CR, RCC_CR_HSERDY) != 0U) && (pRCC_OscInitStruct->HSEState == RCC_HSE_OFF)) { return HAL_ERROR; } } else { /* Set the new HSE configuration ---------------------------------------*/ __HAL_RCC_HSE_CONFIG(pRCC_OscInitStruct->HSEState); /* Check the HSE State */ if (pRCC_OscInitStruct->HSEState != RCC_HSE_OFF) { tickstart = HAL_GetTick(); /* Wait till HSE is ready */ while (READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U) { if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } else { tickstart = HAL_GetTick(); /* Wait till HSE is disabled */ while (READ_BIT(RCC->CR, RCC_CR_HSERDY) != 0U) { if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } } } /*----------------------------- HSI Configuration --------------------------*/ if (((pRCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI) { /* Check the parameters */ assert_param(IS_RCC_HSI(pRCC_OscInitStruct->HSIState)); assert_param(IS_RCC_HSI_CALIBRATION_VALUE(pRCC_OscInitStruct->HSICalibrationValue)); /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */ if ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_HSI) || ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (pll_config == RCC_PLLSOURCE_HSI))) { /* When HSI is used as system clock it will not be disabled */ if ((READ_BIT(RCC->CR, RCC_CR_HSIRDY) != 0U) && (pRCC_OscInitStruct->HSIState == RCC_HSI_OFF)) { return HAL_ERROR; } /* Otherwise, just the calibration is allowed */ else { /* Adjusts the Internal High Speed oscillator (HSI) calibration value */ __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(pRCC_OscInitStruct->HSICalibrationValue); } } else { /* Check the HSI State */ if (pRCC_OscInitStruct->HSIState != RCC_HSI_OFF) { /* Enable the Internal High Speed oscillator (HSI) */ __HAL_RCC_HSI_ENABLE(); tickstart = HAL_GetTick(); /* Wait till HSI is ready */ while (READ_BIT(RCC->CR, RCC_CR_HSIRDY) == 0U) { if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } /* Adjusts the Internal High Speed oscillator (HSI) calibration value */ __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(pRCC_OscInitStruct->HSICalibrationValue); } else { /* Disable the Internal High Speed oscillator (HSI) */ __HAL_RCC_HSI_DISABLE(); tickstart = HAL_GetTick(); /* Wait till HSI is disabled */ while (READ_BIT(RCC->CR, RCC_CR_HSIRDY) != 0U) { if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } } } /*------------------------------ LSI Configuration -------------------------*/ if (((pRCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI) { /* Check the parameters */ assert_param(IS_RCC_LSI(pRCC_OscInitStruct->LSIState)); FlagStatus pwrclkchanged = RESET; /* Update LSI configuration in Backup Domain control register */ /* Requires to enable write access to Backup Domain of necessary */ if (__HAL_RCC_PWR_IS_CLK_DISABLED()) { __HAL_RCC_PWR_CLK_ENABLE(); pwrclkchanged = SET; } if (HAL_IS_BIT_CLR(PWR->DBPR, PWR_DBPR_DBP)) { /* Enable write access to Backup domain */ SET_BIT(PWR->DBPR, PWR_DBPR_DBP); /* Wait for Backup domain Write protection disable */ tickstart = HAL_GetTick(); while (HAL_IS_BIT_CLR(PWR->DBPR, PWR_DBPR_DBP)) { if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } /* Check the LSI State */ if (pRCC_OscInitStruct->LSIState != RCC_LSI_OFF) { uint32_t bdcr_temp = RCC->BDCR; /* Check LSI division factor */ assert_param(IS_RCC_LSIDIV(pRCC_OscInitStruct->LSIDiv)); if (pRCC_OscInitStruct->LSIDiv != (bdcr_temp & RCC_BDCR_LSIPREDIV)) { if (((bdcr_temp & RCC_BDCR_LSIRDY) == RCC_BDCR_LSIRDY) && \ ((bdcr_temp & RCC_BDCR_LSION) != RCC_BDCR_LSION)) { /* If LSIRDY is set while LSION is not enabled, LSIPREDIV can't be updated */ /* The LSIPREDIV cannot be changed if the LSI is used by the IWDG or by the RTC */ return HAL_ERROR; } /* Turn off LSI before changing RCC_BDCR_LSIPREDIV */ if ((bdcr_temp & RCC_BDCR_LSION) == RCC_BDCR_LSION) { __HAL_RCC_LSI_DISABLE(); tickstart = HAL_GetTick(); /* Wait till LSI is disabled */ while (READ_BIT(RCC->BDCR, RCC_BDCR_LSIRDY) != 0U) { if ((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } /* Set LSI division factor */ MODIFY_REG(RCC->BDCR, RCC_BDCR_LSIPREDIV, pRCC_OscInitStruct->LSIDiv); } /* Enable the Internal Low Speed oscillator (LSI) */ __HAL_RCC_LSI_ENABLE(); tickstart = HAL_GetTick(); /* Wait till LSI is ready */ while (READ_BIT(RCC->BDCR, RCC_BDCR_LSIRDY) == 0U) { if ((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } else { /* Disable the Internal Low Speed oscillator (LSI) */ __HAL_RCC_LSI_DISABLE(); tickstart = HAL_GetTick(); /* Wait till LSI is disabled */ while (READ_BIT(RCC->BDCR, RCC_BDCR_LSIRDY) != 0U) { if ((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } /* Restore clock configuration if changed */ if (pwrclkchanged == SET) { __HAL_RCC_PWR_CLK_DISABLE(); } } /*------------------------------ LSE Configuration -------------------------*/ if (((pRCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE) { FlagStatus pwrclkchanged = RESET; /* Check the parameters */ assert_param(IS_RCC_LSE(pRCC_OscInitStruct->LSEState)); /* Update LSE configuration in Backup Domain control register */ /* Requires to enable write access to Backup Domain of necessary */ if (__HAL_RCC_PWR_IS_CLK_DISABLED()) { __HAL_RCC_PWR_CLK_ENABLE(); pwrclkchanged = SET; } if (HAL_IS_BIT_CLR(PWR->DBPR, PWR_DBPR_DBP)) { /* Enable write access to Backup domain */ SET_BIT(PWR->DBPR, PWR_DBPR_DBP); /* Wait for Backup domain Write protection disable */ tickstart = HAL_GetTick(); while (HAL_IS_BIT_CLR(PWR->DBPR, PWR_DBPR_DBP)) { if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } /* Set the new LSE configuration -----------------------------------------*/ if ((pRCC_OscInitStruct->LSEState & RCC_BDCR_LSEON) != 0U) { if ((pRCC_OscInitStruct->LSEState & RCC_BDCR_LSEBYP) != 0U) { /* LSE oscillator bypass enable */ SET_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); SET_BIT(RCC->BDCR, RCC_BDCR_LSEON); } else { /* LSE oscillator enable */ SET_BIT(RCC->BDCR, RCC_BDCR_LSEON); } } else { CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEON); CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); } /* Check the LSE State */ if (pRCC_OscInitStruct->LSEState != RCC_LSE_OFF) { tickstart = HAL_GetTick(); /* Wait till LSE is ready */ while (READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == 0U) { if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } /* Enable LSESYS additionally if requested */ if ((pRCC_OscInitStruct->LSEState & RCC_BDCR_LSESYSEN) != 0U) { SET_BIT(RCC->BDCR, RCC_BDCR_LSESYSEN); /* Wait till LSESYS is ready */ while (READ_BIT(RCC->BDCR, RCC_BDCR_LSESYSRDY) == 0U) { if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } else {