int i2c_stm32_runtime_configure(struct device *dev, u32_t config) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); struct i2c_stm32_data *data = DEV_DATA(dev); I2C_TypeDef *i2c = cfg->i2c; u32_t clock = 0U; int ret; #if defined(CONFIG_SOC_SERIES_STM32F3X) || defined(CONFIG_SOC_SERIES_STM32F0X) LL_RCC_ClocksTypeDef rcc_clocks; /* * STM32F0/3 I2C's independent clock source supports only * HSI and SYSCLK, not APB1. We force clock variable to * SYSCLK frequency. */ LL_RCC_GetSystemClocksFreq(&rcc_clocks); clock = rcc_clocks.SYSCLK_Frequency; #else clock_control_get_rate(device_get_binding(STM32_CLOCK_CONTROL_NAME), (clock_control_subsys_t *) &cfg->pclken, &clock); #endif /* CONFIG_SOC_SERIES_STM32F3X) || CONFIG_SOC_SERIES_STM32F0X */ data->dev_config = config; k_sem_take(&data->bus_mutex, K_FOREVER); LL_I2C_Disable(i2c); LL_I2C_SetMode(i2c, LL_I2C_MODE_I2C); ret = stm32_i2c_configure_timing(dev, clock); k_sem_give(&data->bus_mutex); return ret; }
static int mcux_lpuart_init(struct device *dev) { const struct mcux_lpuart_config *config = dev->config->config_info; lpuart_config_t uart_config; struct device *clock_dev; u32_t clock_freq; clock_dev = device_get_binding(config->clock_name); if (clock_dev == NULL) { return -EINVAL; } if (clock_control_get_rate(clock_dev, config->clock_subsys, &clock_freq)) { return -EINVAL; } LPUART_GetDefaultConfig(&uart_config); uart_config.enableTx = true; uart_config.enableRx = true; uart_config.baudRate_Bps = config->baud_rate; LPUART_Init(config->base, &uart_config, clock_freq); #ifdef CONFIG_UART_INTERRUPT_DRIVEN config->irq_config_func(dev); #endif return 0; }
static int mcux_wdog_install_timeout(struct device *dev, const struct wdt_timeout_cfg *cfg) { const struct mcux_wdog_config *config = dev->config->config_info; struct mcux_wdog_data *data = dev->driver_data; struct device *clock_dev; u32_t clock_freq; if (data->timeout_valid) { LOG_ERR("No more timeouts can be installed"); return -ENOMEM; } clock_dev = device_get_binding(config->clock_name); if (clock_dev == NULL) { return -EINVAL; } if (clock_control_get_rate(clock_dev, config->clock_subsys, &clock_freq)) { return -EINVAL; } WDOG_GetDefaultConfig(&data->wdog_config); data->wdog_config.timeoutValue = clock_freq * cfg->window.max / 1000; if (cfg->window.min) { data->wdog_config.enableWindowMode = true; data->wdog_config.windowValue = clock_freq * cfg->window.min / 1000; } else { data->wdog_config.enableWindowMode = false; data->wdog_config.windowValue = 0; } if ((data->wdog_config.timeoutValue < MIN_TIMEOUT) || (data->wdog_config.timeoutValue < data->wdog_config.windowValue)) { LOG_ERR("Invalid timeout"); return -EINVAL; } data->wdog_config.clockSource = kWDOG_LpoClockSource; data->wdog_config.enableInterrupt = cfg->callback != NULL; data->callback = cfg->callback; data->timeout_valid = true; return 0; }
static int spi_stm32_configure(struct spi_config *config) { const struct spi_stm32_config *cfg = CONFIG_CFG(config); struct spi_stm32_data *data = CONFIG_DATA(config); const u32_t scaler[] = { LL_SPI_BAUDRATEPRESCALER_DIV2, LL_SPI_BAUDRATEPRESCALER_DIV4, LL_SPI_BAUDRATEPRESCALER_DIV8, LL_SPI_BAUDRATEPRESCALER_DIV16, LL_SPI_BAUDRATEPRESCALER_DIV32, LL_SPI_BAUDRATEPRESCALER_DIV64, LL_SPI_BAUDRATEPRESCALER_DIV128, LL_SPI_BAUDRATEPRESCALER_DIV256 }; SPI_TypeDef *spi = cfg->spi; u32_t clock; int br; if (spi_context_configured(&data->ctx, config)) { /* Nothing to do */ return 0; } if (SPI_WORD_SIZE_GET(config->operation) != 8) { return -ENOTSUP; } clock_control_get_rate(device_get_binding(STM32_CLOCK_CONTROL_NAME), (clock_control_subsys_t) &cfg->pclken, &clock); for (br = 1 ; br <= ARRAY_SIZE(scaler) ; ++br) { u32_t clk = clock >> br; if (clk < config->frequency) { break; } } if (br > ARRAY_SIZE(scaler)) { SYS_LOG_ERR("Unsupported frequency %uHz, max %uHz, min %uHz", config->frequency, clock >> 1, clock >> ARRAY_SIZE(scaler)); return -EINVAL; }
static inline void uart_stm32_set_baudrate(struct device *dev, u32_t baud_rate) { const struct uart_stm32_config *config = DEV_CFG(dev); struct uart_stm32_data *data = DEV_DATA(dev); USART_TypeDef *UartInstance = UART_STRUCT(dev); u32_t clock_rate; /* Get clock rate */ clock_control_get_rate(data->clock, (clock_control_subsys_t *)&config->pclken, &clock_rate); #ifdef CONFIG_LPUART_1 if (IS_LPUART_INSTANCE(UartInstance)) { LL_LPUART_SetBaudRate(UartInstance, clock_rate, #ifdef USART_PRESC_PRESCALER LL_USART_PRESCALER_DIV1, #endif baud_rate); } else { #endif /* CONFIG_LPUART_1 */ LL_USART_SetBaudRate(UartInstance, clock_rate, #ifdef USART_PRESC_PRESCALER LL_USART_PRESCALER_DIV1, #endif #ifdef USART_CR1_OVER8 LL_USART_OVERSAMPLING_16, #endif baud_rate); #ifdef CONFIG_LPUART_1 } #endif /* CONFIG_LPUART_1 */ }
/* * Get the clock rate (cycles per second) for a PWM pin. * * Parameters * dev: Pointer to PWM device structure * pwm: PWM port number * cycles: Pointer to the memory to store clock rate (cycles per second) * * return 0, or negative errno code */ static int pwm_stm32_get_cycles_per_sec(struct device *dev, u32_t pwm, u64_t *cycles) { const struct pwm_stm32_config *cfg = DEV_CFG(dev); struct pwm_stm32_data *data = DEV_DATA(dev); u32_t bus_clk, tim_clk; if (cycles == NULL) { return -EINVAL; } /* Timer clock depends on APB prescaler */ clock_control_get_rate(data->clock, (clock_control_subsys_t *)&cfg->pclken, &bus_clk); tim_clk = __get_tim_clk(bus_clk, (clock_control_subsys_t *)&cfg->pclken); *cycles = (u64_t)(tim_clk / (data->pwm_prescaler + 1)); return 0; }
static inline void uart_stm32_set_baudrate(struct device *dev, u32_t baud_rate) { const struct uart_stm32_config *config = DEV_CFG(dev); struct uart_stm32_data *data = DEV_DATA(dev); #ifdef CONFIG_LPUART_1 USART_TypeDef *UartInstance = UART_STRUCT(dev); #endif u32_t clock_rate; /* Get clock rate */ clock_control_get_rate(data->clock, (clock_control_subsys_t *)&config->pclken, &clock_rate); #ifdef CONFIG_LPUART_1 if (IS_LPUART_INSTANCE(UartInstance)) { uart_stm32_lpuart_set_baud_rate(dev, clock_rate, baud_rate); } else { uart_stm32_usart_set_baud_rate(dev, clock_rate, baud_rate); } #else uart_stm32_usart_set_baud_rate(dev, clock_rate, baud_rate); #endif }
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; }