/** * @brief Initialize some features of ADC common parameters * (all ADC instances belonging to the same ADC common instance) * and multimode (for devices with several ADC instances available). * @note The setting of ADC common parameters is conditioned to * ADC instances state: * All ADC instances belonging to the same ADC common instance * must be disabled. * @param ADCxy_COMMON ADC common instance * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) * @param ADC_CommonInitStruct Pointer to a @ref LL_ADC_CommonInitTypeDef structure * @retval An ErrorStatus enumeration value: * - SUCCESS: ADC common registers are initialized * - ERROR: ADC common registers are not initialized */ ErrorStatus LL_ADC_CommonInit(ADC_Common_TypeDef *ADCxy_COMMON, LL_ADC_CommonInitTypeDef *ADC_CommonInitStruct) { ErrorStatus status = SUCCESS; /* Check the parameters */ assert_param(IS_ADC_COMMON_INSTANCE(ADCxy_COMMON)); assert_param(IS_LL_ADC_COMMON_CLOCK(ADC_CommonInitStruct->CommonClock)); #if defined(ADC_MULTIMODE_SUPPORT) assert_param(IS_LL_ADC_MULTI_MODE(ADC_CommonInitStruct->Multimode)); if(ADC_CommonInitStruct->Multimode != LL_ADC_MULTI_INDEPENDENT) { assert_param(IS_LL_ADC_MULTI_DMA_TRANSFER(ADC_CommonInitStruct->MultiDMATransfer)); assert_param(IS_LL_ADC_MULTI_TWOSMP_DELAY(ADC_CommonInitStruct->MultiTwoSamplingDelay)); } #endif /* ADC_MULTIMODE_SUPPORT */ /* Note: Hardware constraint (refer to description of functions */ /* "LL_ADC_SetCommonXXX()" and "LL_ADC_SetMultiXXX()"): */ /* On this STM32 family, setting of these features is conditioned to */ /* ADC state: */ /* All ADC instances of the ADC common group must be disabled. */ if(__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(ADCxy_COMMON) == 0U) { /* Configuration of ADC hierarchical scope: */ /* - common to several ADC */ /* (all ADC instances belonging to the same ADC common instance) */ /* - Set ADC clock (conversion clock) */ /* - multimode (if several ADC instances available on the */ /* selected device) */ /* - Set ADC multimode configuration */ /* - Set ADC multimode DMA transfer */ /* - Set ADC multimode: delay between 2 sampling phases */ #if defined(ADC_MULTIMODE_SUPPORT) if(ADC_CommonInitStruct->Multimode != LL_ADC_MULTI_INDEPENDENT) { MODIFY_REG(ADCxy_COMMON->CCR, ADC_CCR_CKMODE | ADC_CCR_PRESC | ADC_CCR_DUAL | ADC_CCR_MDMA | ADC_CCR_DELAY , ADC_CommonInitStruct->CommonClock | ADC_CommonInitStruct->Multimode | ADC_CommonInitStruct->MultiDMATransfer | ADC_CommonInitStruct->MultiTwoSamplingDelay ); } else { MODIFY_REG(ADCxy_COMMON->CCR, ADC_CCR_CKMODE | ADC_CCR_PRESC | ADC_CCR_DUAL | ADC_CCR_MDMA | ADC_CCR_DELAY , ADC_CommonInitStruct->CommonClock | LL_ADC_MULTI_INDEPENDENT ); } #else LL_ADC_SetCommonClock(ADCxy_COMMON, ADC_CommonInitStruct->CommonClock); #endif } else { /* Initialization error: One or several ADC instances belonging to */ /* the same ADC common instance are not disabled. */ status = ERROR; } return status; }
static int adc_stm32_init(struct device *dev) { struct adc_stm32_data *data = dev->driver_data; const struct adc_stm32_cfg *config = dev->config->config_info; struct device *clk = device_get_binding(STM32_CLOCK_CONTROL_NAME); ADC_TypeDef *adc = (ADC_TypeDef *)config->base; LOG_DBG("Initializing...."); data->dev = dev; #if defined(CONFIG_SOC_SERIES_STM32F0X) || defined(CONFIG_SOC_SERIES_STM32L0X) /* * All conversion time for all channels on one ADC instance for F0 and * L0 series chips has to be the same. This additional variable is for * checking if the conversion time selection of all channels on one ADC * instance is the same. */ data->acq_time_index = -1; #endif if (clock_control_on(clk, (clock_control_subsys_t *) &config->pclken) != 0) { return -EIO; } #if defined(CONFIG_SOC_SERIES_STM32L4X) /* * L4 series STM32 needs to be awaken from deep sleep mode, and restore * its calibration parameters if there are some previously stored * calibration parameters. */ LL_ADC_DisableDeepPowerDown(adc); #endif /* * F3 and L4 ADC modules need some time to be stabilized before * performing any enable or calibration actions. */ #if defined(CONFIG_SOC_SERIES_STM32F3X) || \ defined(CONFIG_SOC_SERIES_STM32L4X) LL_ADC_EnableInternalRegulator(adc); k_busy_wait(LL_ADC_DELAY_INTERNAL_REGUL_STAB_US); #endif #if defined(CONFIG_SOC_SERIES_STM32F0X) || \ defined(CONFIG_SOC_SERIES_STM32L0X) LL_ADC_SetClock(adc, LL_ADC_CLOCK_SYNC_PCLK_DIV4); #elif defined(CONFIG_SOC_SERIES_STM32F3X) || \ defined(CONFIG_SOC_SERIES_STM32L4X) LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(), LL_ADC_CLOCK_SYNC_PCLK_DIV4); #endif #if !defined(CONFIG_SOC_SERIES_STM32F2X) && \ !defined(CONFIG_SOC_SERIES_STM32F4X) && \ !defined(CONFIG_SOC_SERIES_STM32F7X) && \ !defined(CONFIG_SOC_SERIES_STM32F1X) /* * Calibration of F1 series has to be started after ADC Module is * enabled. */ adc_stm32_calib(dev); #endif #if defined(CONFIG_SOC_SERIES_STM32F0X) || \ defined(CONFIG_SOC_SERIES_STM32L0X) if (LL_ADC_IsActiveFlag_ADRDY(adc)) { LL_ADC_ClearFlag_ADRDY(adc); } /* * These two series STM32 has one internal voltage reference source * to be enabled. */ LL_ADC_SetCommonPathInternalCh(ADC, LL_ADC_PATH_INTERNAL_VREFINT); #endif #if defined(CONFIG_SOC_SERIES_STM32F0X) || \ defined(CONFIG_SOC_SERIES_STM32F3X) || \ defined(CONFIG_SOC_SERIES_STM32L0X) || \ defined(CONFIG_SOC_SERIES_STM32L4X) /* * ADC modules on these series have to wait for some cycles to be * enabled. */ u32_t adc_rate, wait_cycles; if (clock_control_get_rate(clk, (clock_control_subsys_t *) &config->pclken, &adc_rate) < 0) { LOG_ERR("ADC clock rate get error."); } wait_cycles = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / adc_rate * LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES; for (int i = wait_cycles; i >= 0; i--) ; #endif LL_ADC_Enable(adc); #ifdef CONFIG_SOC_SERIES_STM32L4X /* * Enabling ADC modules in L4 series may fail if they are still not * stabilized, this will wait for a short time to ensure ADC modules * are properly enabled. */ u32_t countTimeout = 0; while (LL_ADC_IsActiveFlag_ADRDY(adc) == 0) { if (LL_ADC_IsEnabled(adc) == 0UL) { LL_ADC_Enable(adc); countTimeout++; if (countTimeout == 10) { return -ETIMEDOUT; } } } #endif config->irq_cfg_func(); #ifdef CONFIG_SOC_SERIES_STM32F1X /* Calibration of F1 must starts after two cycles after ADON is set. */ LL_ADC_StartCalibration(adc); LL_ADC_REG_SetTriggerSource(adc, LL_ADC_REG_TRIG_SOFTWARE); #endif adc_context_unlock_unconditionally(&data->ctx); return 0; }