From 41590f2450b4bc599eeb976208e100fb5dd776b8 Mon Sep 17 00:00:00 2001 From: Stefan Jaritz Date: Thu, 28 Jun 2018 17:16:04 +0100 Subject: [PATCH 1/4] added: smt32f4 dts support for uart1 using PA15 and PA10 --- dts/arm/st/stm32f4-pinctrl.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dts/arm/st/stm32f4-pinctrl.dtsi b/dts/arm/st/stm32f4-pinctrl.dtsi index 0aa1739f4f6af8..c220f8a94ce681 100644 --- a/dts/arm/st/stm32f4-pinctrl.dtsi +++ b/dts/arm/st/stm32f4-pinctrl.dtsi @@ -27,6 +27,12 @@ tx = ; }; }; + usart1_pins_d: usart1@3 { + rx_tx { + rx = ; + tx = ; + }; + }; usart2_pins_a: usart2@0 { rx_tx { rx = ; From 223d848ffcd2a3b29889581d3cf1d63b2599eacb Mon Sep 17 00:00:00 2001 From: Stefan Jaritz Date: Thu, 28 Jun 2018 17:17:08 +0100 Subject: [PATCH 2/4] added: experimental stm32f4 adc driver --- drivers/adc/CMakeLists.txt | 1 + drivers/adc/Kconfig | 17 ++ drivers/adc/Kconfig.stm32f4 | 373 +++++++++++++++++++++++++++ drivers/adc/adc_stm32f4.c | 501 ++++++++++++++++++++++++++++++++++++ drivers/adc/adc_stm32f4.h | 82 ++++++ 5 files changed, 974 insertions(+) create mode 100644 drivers/adc/Kconfig.stm32f4 create mode 100644 drivers/adc/adc_stm32f4.c create mode 100644 drivers/adc/adc_stm32f4.h diff --git a/drivers/adc/CMakeLists.txt b/drivers/adc/CMakeLists.txt index 787145630d39f1..99420a18405dfb 100644 --- a/drivers/adc/CMakeLists.txt +++ b/drivers/adc/CMakeLists.txt @@ -6,5 +6,6 @@ zephyr_library_sources_ifdef(CONFIG_ADC_QMSI adc_qmsi.c) zephyr_library_sources_ifdef(CONFIG_ADC_QMSI_SS adc_qmsi_ss.c) zephyr_library_sources_ifdef(CONFIG_ADC_SAM_AFEC adc_sam_afec.c) zephyr_library_sources_ifdef(CONFIG_ADC_TI_ADC108S102 adc_ti_adc108s102.c) +zephyr_library_sources_ifdef(CONFIG_ADC_STM32F4 adc_stm32f4.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE adc_handlers.c) diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index e3610c51c6ceb6..e56ab89413125c 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -74,6 +74,20 @@ config ADC_1_IRQ_PRI prompt "ADC 1 interrupt priority" default 2 +config ADC_2 + bool "Enable ADC 2" + +config ADC_2_NAME + string "ADC 2 Driver's name" + depends on ADC_2 && !HAS_DTS_ADC + default "ADC_2" + +config ADC_2_IRQ_PRI + int + depends on ADC_2 && !HAS_DTS_ADC + prompt "ADC 2 interrupt priority" + default 2 + source "drivers/adc/Kconfig.dw" source "drivers/adc/Kconfig.mcux" @@ -84,4 +98,7 @@ source "drivers/adc/Kconfig.sam_afec" source "drivers/adc/Kconfig.ti_adc108s102" +source "drivers/adc/Kconfig.stm32f4" + endif # ADC + diff --git a/drivers/adc/Kconfig.stm32f4 b/drivers/adc/Kconfig.stm32f4 new file mode 100644 index 00000000000000..78a2a5ca49befc --- /dev/null +++ b/drivers/adc/Kconfig.stm32f4 @@ -0,0 +1,373 @@ +# Kconfig - ADC configuration options + +# +# Copyright (c) 2015 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +menuconfig ADC_STM32F4 + bool "STM32F4 ADC driver" + depends on SOC_FAMILY_STM32 + select USE_STM32_HAL_GPIO + select USE_STM32_HAL_GPIO_EX + select USE_STM32_HAL_ADC + select USE_STM32_HAL_ADC_EX + select USE_STM32_HAL_CORTEX + help + Enable the driver implementation for the stm32f4xx ADC + +if ADC_STM32F4 + + menu ADC_0 + config ADC0_CHAN0 + bool "channel 0 (PA0)" + default n + depends on ADC_0 + help + Enables ADC channel 0 at pin PA0 + + config ADC0_CHAN1 + bool "channel 1 (PA1)" + default n + depends on ADC_0 + help + Enables ADC channel 1 at pin PA1 + + config ADC0_CHAN2 + bool "channel 2 (PA2)" + default n + depends on ADC_0 + help + Enables ADC channel 2 at pin PA2 + + config ADC0_CHAN3 + bool "channel 3 (PA3)" + default n + depends on ADC_0 + help + Enables ADC channel 3 at pin PA3 + + config ADC0_CHAN4 + bool "channel 4 (PA4)" + default n + depends on ADC_0 + help + Enables ADC channel 4 at pin PA4 + + config ADC0_CHAN5 + bool "channel 5 (PA5)" + default n + depends on ADC_0 + help + Enables ADC channel 5 at pin PA5 + + config ADC0_CHAN6 + bool "channel 6 (PA6)" + default n + depends on ADC_0 + help + Enables ADC channel 6 at pin PA6 + + config ADC0_CHAN7 + bool "channel 7 (PA7)" + default n + depends on ADC_0 + help + Enables ADC channel 7 at pin PA7 + + config ADC0_CHAN8 + bool "channel 8 (PB0)" + default n + depends on ADC_0 + help + Enables ADC channel 8 at pin PB0 + + config ADC0_CHAN9 + bool "channel 9 (PB1)" + default n + depends on ADC_0 + help + Enables ADC channel 9 at pin PB1 + + config ADC0_CHAN10 + bool "channel 10 (PC0)" + default n + depends on ADC_0 + help + Enables ADC channel 10 at pin PC0 + + config ADC0_CHAN11 + bool "channel 11 (PC1)" + default n + depends on ADC_0 + help + Enables ADC channel 11 at pin PC1 + + config ADC0_CHAN12 + bool "channel 12 (PC2)" + default n + depends on ADC_0 + help + Enables ADC channel 12 at pin PC2 + + config ADC0_CHAN13 + bool "channel 13 (PC3)" + default n + depends on ADC_0 + help + Enables ADC channel 13 at pin PC3 + + config ADC0_CHAN14 + bool "channel 14 (PC4)" + default n + depends on ADC_0 + help + Enables ADC channel 14 at pin PC4 + + config ADC0_CHAN15 + bool "channel 15 (PC5)" + default n + depends on ADC_0 + help + Enables ADC channel 15 at pin PC5 + + config ADC0_CHAN_TEMP + bool "channel 16 (temp)" + default n + depends on ADC_0 + help + Enables ADC temperature channel + + config ADC0_CHAN_VREFINT + bool "channel 17 (Vrefint)" + default n + depends on ADC_0 + help + Enables ADC internal voltage reference channel + + config ADC0_CHAN_VABT + bool "channel 18 (VBat)" + default n + depends on ADC_0 + help + Enables ADC voltage battery channel + endmenu + + menu ADC_1 + config ADC1_CHAN0 + bool "channel 0 (PA0)" + default n + depends on ADC_1 + help + Enables ADC channel 0 at pin PA0 + + config ADC1_CHAN1 + bool "channel 1 (PA1)" + default n + depends on ADC_1 + help + Enables ADC channel 1 at pin PA1 + + config ADC1_CHAN2 + bool "channel 2 (PA2)" + default n + depends on ADC_1 + help + Enables ADC channel 2 at pin PA2 + + config ADC1_CHAN3 + bool "channel 3 (PA3)" + default n + depends on ADC_1 + help + Enables ADC channel 3 at pin PA3 + + config ADC1_CHAN4 + bool "channel 4 (PA4)" + default n + depends on ADC_1 + help + Enables ADC channel 4 at pin PA4 + + config ADC1_CHAN5 + bool "channel 5 (PA5)" + default n + depends on ADC_1 + help + Enables ADC channel 5 at pin PA5 + + config ADC1_CHAN6 + bool "channel 6 (PA6)" + default n + depends on ADC_1 + help + Enables ADC channel 6 at pin PA6 + + config ADC1_CHAN7 + bool "channel 7 (PA7)" + default n + depends on ADC_1 + help + Enables ADC channel 7 at pin PA7 + + config ADC1_CHAN8 + bool "channel 8 (PB0)" + default n + depends on ADC_1 + help + Enables ADC channel 8 at pin PB0 + + config ADC1_CHAN9 + bool "channel 9 (PB1)" + default n + depends on ADC_1 + help + Enables ADC channel 9 at pin PB1 + + config ADC1_CHAN10 + bool "channel 10 (PC0)" + default n + depends on ADC_1 + help + Enables ADC channel 10 at pin PC0 + + config ADC1_CHAN11 + bool "channel 11 (PC1)" + default n + depends on ADC_1 + help + Enables ADC channel 11 at pin PC1 + + config ADC1_CHAN12 + bool "channel 12 (PC2)" + default n + depends on ADC_1 + help + Enables ADC channel 12 at pin PC2 + + config ADC1_CHAN13 + bool "channel 13 (PC3)" + default n + depends on ADC_1 + help + Enables ADC channel 13 at pin PC3 + + config ADC1_CHAN14 + bool "channel 14 (PC4)" + default n + depends on ADC_1 + help + Enables ADC channel 14 at pin PC4 + + config ADC1_CHAN15 + bool "channel 15 (PC5)" + default n + depends on ADC_1 + help + Enables ADC channel 15 at pin PC5 + + config ADC1_CHAN_TEMP + bool "channel 16 (temp)" + default n + depends on ADC_1 + help + Enables ADC temperature channel + + config ADC1_CHAN_VREFINT + bool "channel 17 (Vrefint)" + default n + depends on ADC_1 + help + Enables ADC internal voltage reference channel + + config ADC1_CHAN_VABT + bool "channel 18 (VBat)" + default n + depends on ADC_1 + help + Enables ADC voltage battery channel + endmenu + + menu ADC_2 + config ADC2_CHAN0 + bool "channel 0 (PA0)" + default n + depends on ADC_2 + help + Enables ADC channel 0 at pin PA0 + + + config ADC2_CHAN1 + bool "channel 1 (PA1)" + default n + depends on ADC_2 + help + Enables ADC channel 1 at pin PA1 + + config ADC2_CHAN2 + bool "channel 2 (PA2)" + default n + depends on ADC_2 + help + Enables ADC channel 2 at pin PA2 + + config ADC2_CHAN3 + bool "channel 3 (PA3)" + default n + depends on ADC_2 + help + Enables ADC channel 3 at pin PA3 + + config ADC2_CHAN10 + bool "channel 10 (PC0)" + default n + depends on ADC_2 + help + Enables ADC channel 10 at pin PC0 + + config ADC2_CHAN11 + bool "channel 11 (PC1)" + default n + depends on ADC_2 + help + Enables ADC channel 11 at pin PC1 + + config ADC2_CHAN12 + bool "channel 12 (PC2)" + default n + depends on ADC_2 + help + Enables ADC channel 12 at pin PC2 + + config ADC2_CHAN13 + bool "channel 13 (PC3)" + default n + depends on ADC_2 + help + Enables ADC channel 13 at pin PC3 + + config ADC2_CHAN_TEMP + bool "channel 16 (temp)" + default n + depends on ADC_2 + help + Enables ADC temperature channel + + config ADC2_CHAN_VREFINT + bool "channel 17 (Vrefint)" + default n + depends on ADC_2 + help + Enables ADC internal voltage reference channel + + config ADC2_CHAN_VABT + bool "channel 18 (VBat)" + default n + depends on ADC_2 + help + Enables ADC voltage battery channel + endmenu + +endif # ADC_STM32F4 + diff --git a/drivers/adc/adc_stm32f4.c b/drivers/adc/adc_stm32f4.c new file mode 100644 index 00000000000000..981dc35ec04b6c --- /dev/null +++ b/drivers/adc/adc_stm32f4.c @@ -0,0 +1,501 @@ +/* adc_dw.c - Designware ADC driver */ + +/* + * Copyright (c) 2015 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include + +#define SYS_LOG_DOMAIN "SMT32F4_ADC" +#define SYS_LOG_LEVEL CONFIG_SYS_LOG_ADC_LEVEL +#include + +#include + +#include +#include +#include +#include + +#include "adc_stm32f4.h" + +#define ADC_STM32F4_SETBITMASK(bit) (1 << (bit)) + +static void adc_stm32f4_enable(struct device *dev) +{ + const struct adc_config *config = dev->config->config_info; + + SYS_LOG_DBG("adc%u enable", (unsigned int)config->adcDevNum); +} + +static void adc_stm32f4_disable(struct device *dev) +{ + const struct adc_config *config = dev->config->config_info; + + SYS_LOG_DBG("adc%u disable", (unsigned int)config->adcDevNum); + +} + +static int adc_stm32f4_read(struct device *dev, struct adc_seq_table *seq_tbl) +{ + struct adc_drvData *drvData = dev->driver_data; + const struct adc_config *config = dev->config->config_info; + uint16_t val; + adc_channel_index_t i; + uint32_t activeChannels; + int rc; + struct adc_seq_entry * pE; + + SYS_LOG_DBG("start adc%u conversion", (unsigned int)config->adcDevNum); + // ok let's read for once the values + HAL_ADC_Start(&drvData->hadc); + // let's iterate through the sequence table + pE = seq_tbl->entries; + activeChannels = config->activeChannels; + i = adcChannel_0; + rc = stm32adcError_None; + while(activeChannels) { + if(activeChannels & 0x1) { + if (HAL_ADC_PollForConversion(&drvData->hadc, 100) == HAL_OK) { + val = HAL_ADC_GetValue(&drvData->hadc); + } else { + rc = stm32adcError_adcHALerror; + val = 0; + } + *((uint16_t *) pE->buffer) = val; + pE++; + } + activeChannels >>= 1; + i++; + } + + HAL_ADC_Stop(&drvData->hadc); + + SYS_LOG_DBG("end adc%u conversion with rc=%i", (unsigned int)config->adcDevNum, rc); + return rc; +} + +static struct adc_driver_api api_funcs = { + .enable = adc_stm32f4_enable, + .disable = adc_stm32f4_disable, + .read = adc_stm32f4_read, +}; + + +int adc_stm32f4_cfgChannel (ADC_HandleTypeDef * phadc, uint32_t c, uint32_t r) { + ADC_ChannelConfTypeDef cfg; + GPIO_InitTypeDef gpioCfg; + GPIO_TypeDef * GPIOport; + + SYS_LOG_DBG("try to config adc channel %u (rank=%u) ...", c, r); + + cfg.Rank = r; + cfg.SamplingTime = ADC_SAMPLETIME_480CYCLES; + cfg.Offset = 0; + + gpioCfg.Mode = GPIO_MODE_ANALOG; + gpioCfg.Pull = GPIO_NOPULL; + + // set the pins and special function registers + GPIOport = NULL; + + switch (c) { + case adcChannel_0: + GPIOport = GPIOA; + gpioCfg.Pin = GPIO_PIN_0; + cfg.Channel = ADC_CHANNEL_0; + break; + case adcChannel_1: + GPIOport = GPIOA; + gpioCfg.Pin = GPIO_PIN_1; + cfg.Channel = ADC_CHANNEL_1; + break; + case adcChannel_2: + GPIOport = GPIOA; + gpioCfg.Pin = GPIO_PIN_2; + cfg.Channel = ADC_CHANNEL_2; + break; + case adcChannel_3: + GPIOport = GPIOA; + gpioCfg.Pin = GPIO_PIN_3; + cfg.Channel = ADC_CHANNEL_3; + break; + case adcChannel_4: + GPIOport = GPIOA; + gpioCfg.Pin = GPIO_PIN_4; + cfg.Channel = ADC_CHANNEL_4; + break; + case adcChannel_5: + GPIOport = GPIOA; + gpioCfg.Pin = GPIO_PIN_5; + cfg.Channel = ADC_CHANNEL_5; + break; + case adcChannel_6: + GPIOport = GPIOA; + gpioCfg.Pin = GPIO_PIN_6; + cfg.Channel = ADC_CHANNEL_6; + break; + case adcChannel_7: + GPIOport = GPIOA; + gpioCfg.Pin = GPIO_PIN_7; + cfg.Channel = ADC_CHANNEL_7; + break; + case adcChannel_8: + GPIOport = GPIOB; + gpioCfg.Pin = GPIO_PIN_0; + cfg.Channel = ADC_CHANNEL_8; + break; + case adcChannel_9: + GPIOport = GPIOB; + gpioCfg.Pin = GPIO_PIN_1; + cfg.Channel = ADC_CHANNEL_9; + break; + case adcChannel_10: + GPIOport = GPIOC; + gpioCfg.Pin = GPIO_PIN_0; + cfg.Channel = ADC_CHANNEL_10; + break; + case adcChannel_11: + GPIOport = GPIOC; + gpioCfg.Pin = GPIO_PIN_1; + cfg.Channel = ADC_CHANNEL_11; + break; + case adcChannel_12: + GPIOport = GPIOC; + gpioCfg.Pin = GPIO_PIN_2; + cfg.Channel = ADC_CHANNEL_12; + break; + case adcChannel_13: + GPIOport = GPIOC; + gpioCfg.Pin = GPIO_PIN_3; + cfg.Channel = ADC_CHANNEL_13; + break; + case adcChannel_14: + GPIOport = GPIOC; + gpioCfg.Pin = GPIO_PIN_4; + cfg.Channel = ADC_CHANNEL_14; + break; + case adcChannel_15: + GPIOport = GPIOC; + gpioCfg.Pin = GPIO_PIN_5; + cfg.Channel = ADC_CHANNEL_15; + break; + + case adcChannel_vref: + cfg.Channel = ADC_CHANNEL_VREFINT; + ADC->CCR |= ADC_CCR_TSVREFE; + break; + + case adcChannel_temp: + cfg.Channel = ADC_CHANNEL_TEMPSENSOR; + break; + + case adcChannel_vbat: + cfg.Channel = ADC_CHANNEL_VBAT; + ADC->CCR |= ADC_CCR_VBATE; + break; + + default: + // none + break; + } + if(GPIOport) HAL_GPIO_Init(GPIOport, &gpioCfg); + + if (HAL_ADC_ConfigChannel(phadc, &cfg) != HAL_OK) { + SYS_LOG_ERR("config adc channel failed"); + return stm32adcError_adcHALconfigChannel; + } + SYS_LOG_DBG("internal adc channel %u has been configured",cfg.Channel); + + return stm32adcError_None; +} + +int adc_stm32f4_init(struct device *dev) +{ + const struct adc_config *config = dev->config->config_info; + struct adc_drvData *drvData = dev->driver_data; + adc_channel_index_t i; + uint32_t r; + uint32_t activeChannels; + + SYS_LOG_INF("init adc%u", (unsigned int)config->adcDevNum); + + switch(config->adcDevNum) { + #ifdef CONFIG_ADC_0 + case 0: + __HAL_RCC_ADC1_CLK_ENABLE(); + drvData->hadc.Instance = ADC1; + break; + #endif + + #ifdef CONFIG_ADC_1 + case 1: + __HAL_RCC_ADC2_CLK_ENABLE(); + drvData->hadc.Instance = ADC2; + break; + #endif + #ifdef CONFIG_ADC_2 + case 2: + __HAL_RCC_ADC3_CLK_ENABLE(); + drvData->hadc.Instance = ADC3; + break; + #endif + default: + SYS_LOG_ERR("unknown ADC unit"); + return stm32adcError_UnknownADCunit; + } + + drvData->hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; + drvData->hadc.Init.Resolution = ADC_RESOLUTION_12B; + drvData->hadc.Init.ScanConvMode = ENABLE; + drvData->hadc.Init.ContinuousConvMode = ENABLE; + drvData->hadc.Init.DiscontinuousConvMode = DISABLE; + drvData->hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + drvData->hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; + drvData->hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; + drvData->hadc.Init.DMAContinuousRequests = DISABLE; + drvData->hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; + drvData->hadc.Init.NbrOfConversion = 0; + + activeChannels = config->activeChannels; + while(activeChannels) { + if(activeChannels & 1) drvData->hadc.Init.NbrOfConversion++; + activeChannels >>= 1; + } + SYS_LOG_INF("use %u multiplexed channels", (unsigned int) drvData->hadc.Init.NbrOfConversion); + + // start the adc + if (HAL_ADC_Init(&drvData->hadc) != HAL_OK) { + SYS_LOG_ERR("HAL ADC init failed"); + return stm32adcError_adcHALinit; + } + + // setup the sequencer for the channels + i = 0; + r = 1; + activeChannels = config->activeChannels; + while(activeChannels) { + if(activeChannels & 1) { + if(adc_stm32f4_cfgChannel(&drvData->hadc, (uint32_t) i, r)) { + SYS_LOG_ERR("activate adc channel %u failed", i); + return stm32adcError_configChannel; + } else { + SYS_LOG_INF("activate adc channel %u", i); + } + r++; + } + activeChannels >>= 1; + i++; + } + return stm32adcError_None; +} + + +#ifdef CONFIG_ADC_0 + +struct adc_drvData adc_drvData_dev0 = { + }; + +static struct adc_config adc_config_dev0 = { + .adcDevNum = 0, + .activeChannels = 0 + #ifdef CONFIG_ADC0_CHAN0 + + ADC_STM32F4_SETBITMASK(adcChannel_0) + #endif + #ifdef CONFIG_ADC0_CHAN1 + + ADC_STM32F4_SETBITMASK(adcChannel_1) + #endif + #ifdef CONFIG_ADC0_CHAN2 + + ADC_STM32F4_SETBITMASK(adcChannel_2) + #endif + #ifdef CONFIG_ADC0_CHAN3 + + ADC_STM32F4_SETBITMASK(adcChannel_3) + #endif + #ifdef CONFIG_ADC0_CHAN4 + + ADC_STM32F4_SETBITMASK(adcChannel_4) + #endif + #ifdef CONFIG_ADC0_CHAN5 + + ADC_STM32F4_SETBITMASK(adcChannel_5) + #endif + #ifdef CONFIG_ADC0_CHAN6 + + ADC_STM32F4_SETBITMASK(adcChannel_6) + #endif + #ifdef CONFIG_ADC0_CHAN7 + + ADC_STM32F4_SETBITMASK(adcChannel_7) + #endif + #ifdef CONFIG_ADC0_CHAN8 + + ADC_STM32F4_SETBITMASK(adcChannel_8) + #endif + #ifdef CONFIG_ADC0_CHAN9 + + ADC_STM32F4_SETBITMASK(adcChannel_9) + #endif + #ifdef CONFIG_ADC0_CHAN10 + + ADC_STM32F4_SETBITMASK(adcChannel_10) + #endif + #ifdef CONFIG_ADC0_CHAN11 + + ADC_STM32F4_SETBITMASK(adcChannel_11) + #endif + #ifdef CONFIG_ADC0_CHAN12 + + ADC_STM32F4_SETBITMASK(adcChannel_12) + #endif + #ifdef CONFIG_ADC0_CHAN13 + + ADC_STM32F4_SETBITMASK(adcChannel_13) + #endif + #ifdef CONFIG_ADC0_CHAN14 + + ADC_STM32F4_SETBITMASK(adcChannel_14) + #endif + #ifdef CONFIG_ADC0_CHAN15 + + ADC_STM32F4_SETBITMASK(adcChannel_15) + #endif + #ifdef CONFIG_ADC0_CHAN_TEMP + + ADC_STM32F4_SETBITMASK(adcChannel_temp) + #endif + #ifdef CONFIG_ADC0_CHAN_VREFINT + + ADC_STM32F4_SETBITMASK(adcChannel_vref) + #endif + #ifdef CONFIG_ADC0_CHAN_VABT + + ADC_STM32F4_SETBITMASK(adcChannel_vbat) + #endif + , +}; + + +DEVICE_AND_API_INIT(adc_stm32f4, CONFIG_ADC_0_NAME, &adc_stm32f4_init, + &adc_drvData_dev0, &adc_config_dev0, + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, + &api_funcs); +#endif // CONFIG_ADC_0 + +#ifdef CONFIG_ADC_1 + +struct adc_drvData adc_drvData_dev1 = { + }; + +static struct adc_config adc_config_dev1 = { + .adcDevNum = 0, + .activeChannels = 0 + #ifdef CONFIG_ADC1_CHAN0 + + ADC_STM32F4_SETBITMASK(adcChannel_0) + #endif + #ifdef CONFIG_ADC1_CHAN1 + + ADC_STM32F4_SETBITMASK(adcChannel_1) + #endif + #ifdef CONFIG_ADC1_CHAN2 + + ADC_STM32F4_SETBITMASK(adcChannel_2) + #endif + #ifdef CONFIG_ADC1_CHAN3 + + ADC_STM32F4_SETBITMASK(adcChannel_3) + #endif + #ifdef CONFIG_ADC1_CHAN4 + + ADC_STM32F4_SETBITMASK(adcChannel_4) + #endif + #ifdef CONFIG_ADC1_CHAN5 + + ADC_STM32F4_SETBITMASK(adcChannel_5) + #endif + #ifdef CONFIG_ADC1_CHAN6 + + ADC_STM32F4_SETBITMASK(adcChannel_6) + #endif + #ifdef CONFIG_ADC1_CHAN7 + + ADC_STM32F4_SETBITMASK(adcChannel_7) + #endif + #ifdef CONFIG_ADC1_CHAN8 + + ADC_STM32F4_SETBITMASK(adcChannel_8) + #endif + #ifdef CONFIG_ADC1_CHAN9 + + ADC_STM32F4_SETBITMASK(adcChannel_9) + #endif + #ifdef CONFIG_ADC1_CHAN10 + + ADC_STM32F4_SETBITMASK(adcChannel_10) + #endif + #ifdef CONFIG_ADC1_CHAN11 + + ADC_STM32F4_SETBITMASK(adcChannel_11) + #endif + #ifdef CONFIG_ADC1_CHAN12 + + ADC_STM32F4_SETBITMASK(adcChannel_12) + #endif + #ifdef CONFIG_ADC1_CHAN13 + + ADC_STM32F4_SETBITMASK(adcChannel_13) + #endif + #ifdef CONFIG_ADC1_CHAN14 + + ADC_STM32F4_SETBITMASK(adcChannel_14) + #endif + #ifdef CONFIG_ADC1_CHAN15 + + ADC_STM32F4_SETBITMASK(adcChannel_15) + #endif + #ifdef CONFIG_ADC1_CHAN_TEMP + + ADC_STM32F4_SETBITMASK(adcChannel_temp) + #endif + #ifdef CONFIG_ADC1_CHAN_VREFINT + + ADC_STM32F4_SETBITMASK(adcChannel_vref) + #endif + #ifdef CONFIG_ADC1_CHAN_VABT + + ADC_STM32F4_SETBITMASK(adcChannel_vbat) + #endif + , +}; + + +DEVICE_AND_API_INIT(adc_stm32f4, CONFIG_ADC_1_NAME, &adc_stm32f4_init, + &adc_drvData_dev1, &adc_config_dev1, + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, + &api_funcs); +#endif // CONFIG_ADC_1 + +#ifdef CONFIG_ADC_2 + +struct adc_drvData adc_drvData_dev2 = { + }; + +static struct adc_config adc_config_dev2 = { + .adcDevNum = 0, + .activeChannels = 0 + #ifdef CONFIG_ADC2_CHAN0 + + ADC_STM32F4_SETBITMASK(adcChannel_0) + #endif + #ifdef CONFIG_ADC2_CHAN1 + + ADC_STM32F4_SETBITMASK(adcChannel_1) + #endif + #ifdef CONFIG_ADC2_CHAN2 + + ADC_STM32F4_SETBITMASK(adcChannel_2) + #endif + #ifdef CONFIG_ADC2_CHAN3 + + ADC_STM32F4_SETBITMASK(adcChannel_3) + #endif + #ifdef CONFIG_ADC2_CHAN10 + + ADC_STM32F4_SETBITMASK(adcChannel_10) + #endif + #ifdef CONFIG_ADC2_CHAN11 + + ADC_STM32F4_SETBITMASK(adcChannel_11) + #endif + #ifdef CONFIG_ADC2_CHAN12 + + ADC_STM32F4_SETBITMASK(adcChannel_12) + #endif + #ifdef CONFIG_ADC2_CHAN13 + + ADC_STM32F4_SETBITMASK(adcChannel_13) + #endif + #ifdef CONFIG_ADC2_CHAN_TEMP + + ADC_STM32F4_SETBITMASK(adcChannel_temp) + #endif + #ifdef CONFIG_ADC2_CHAN_VREFINT + + ADC_STM32F4_SETBITMASK(adcChannel_vref) + #endif + #ifdef CONFIG_ADC2_CHAN_VABT + + ADC_STM32F4_SETBITMASK(adcChannel_vbat) + #endif + , +}; + + +DEVICE_AND_API_INIT(adc_stm32f4, CONFIG_ADC_2_NAME, &adc_stm32f4_init, + &adc_drvData_dev2, &adc_config_dev2, + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, + &api_funcs); +#endif // CONFIG_ADC_2 diff --git a/drivers/adc/adc_stm32f4.h b/drivers/adc/adc_stm32f4.h new file mode 100644 index 00000000000000..b145dde480f00a --- /dev/null +++ b/drivers/adc/adc_stm32f4.h @@ -0,0 +1,82 @@ +// +// STM32F4xx HAL ADC driver +// +// author: Stefan Jaritz +// 2018 Kokoon Technology Limited +#ifndef STM32F4_ADC_H_ +#define STM32F4_ADC_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +//! type and enum for channel ids +typedef enum adcChannels { + adcChannel_0 = ADC_CHANNEL_0, + adcChannel_1 = ADC_CHANNEL_1, + adcChannel_2 = ADC_CHANNEL_2, + adcChannel_3 = ADC_CHANNEL_3, + adcChannel_4 = ADC_CHANNEL_4, + adcChannel_5 = ADC_CHANNEL_5, + adcChannel_6 = ADC_CHANNEL_6, + adcChannel_7 = ADC_CHANNEL_7, + adcChannel_8 = ADC_CHANNEL_8, + adcChannel_9 = ADC_CHANNEL_9, + adcChannel_10 = ADC_CHANNEL_10, + adcChannel_11 = ADC_CHANNEL_11, + adcChannel_12 = ADC_CHANNEL_12, + adcChannel_13 = ADC_CHANNEL_13, + adcChannel_14 = ADC_CHANNEL_14, + adcChannel_15 = ADC_CHANNEL_15, + adcChannel_temp = ADC_CHANNEL_TEMPSENSOR, // 16 + adcChannel_vref = ADC_CHANNEL_VREFINT, // 17 + adcChannel_vbat = ADC_CHANNEL_VBAT, // 18 + adcChannel_max, + adcChannel_unused, +} adc_channel_index_t; + +enum stm32adcErrors { + stm32adcError_None = 0, + stm32adcError_HALerror = 10, + stm32adcError_adcHALinit, + stm32adcError_adcHALconfigChannel, + stm32adcError_adcHALerror, + stm32adcError_drvError = 100, + stm32adcError_configChannel, + stm32adcError_UnknownADCunit, +}; + +//! definition of the config structure +typedef struct adc_config { + uint32_t adcDevNum; // number of the device + uint32_t activeChannels; // bit mask defining the channels +} adc_config_t; + +//! defiuntion of the driver data +typedef struct adc_drvData { + // handle to adc defintion + ADC_HandleTypeDef hadc; +} adc_drvData_t; + + +// +// @brief ADC Initialization function. +// +// Inits device model for the ADC IP from Dataware. +// +// @param dev Pointer to the device structure descriptor that +// will be initialized. +// +// @return Integer: 0 for success, error otherwise. +// +int adc_stm32f4_init(struct device *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4_ADC_H_ */ From 67acdafda0829a821bfe773d14630035c954f294 Mon Sep 17 00:00:00 2001 From: Stefan Jaritz Date: Sun, 1 Jul 2018 19:37:37 +0100 Subject: [PATCH 3/4] changed rx pin to "STM32_PUPDR_NO_PULL" As mentioned, for rx no resistor is needed. --- dts/arm/st/stm32f4-pinctrl.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dts/arm/st/stm32f4-pinctrl.dtsi b/dts/arm/st/stm32f4-pinctrl.dtsi index c220f8a94ce681..e35fa351513e0a 100644 --- a/dts/arm/st/stm32f4-pinctrl.dtsi +++ b/dts/arm/st/stm32f4-pinctrl.dtsi @@ -29,7 +29,7 @@ }; usart1_pins_d: usart1@3 { rx_tx { - rx = ; + rx = ; tx = ; }; }; From ea2f4125136b7a904d22bb7be6d1ead8c47dcc45 Mon Sep 17 00:00:00 2001 From: Stefan Jaritz Date: Fri, 20 Jul 2018 17:58:59 +0100 Subject: [PATCH 4/4] changed: irq based sample conversion. Reading adc now is waiting while reading for an interrupt in that a semaphore is set. No STM32HAL waiting - instead use of sem_take function. --- drivers/adc/Kconfig.stm32f4 | 8 ++++ drivers/adc/adc_stm32f4.c | 93 ++++++++++++++++++++++++++++--------- drivers/adc/adc_stm32f4.h | 15 +++--- 3 files changed, 89 insertions(+), 27 deletions(-) diff --git a/drivers/adc/Kconfig.stm32f4 b/drivers/adc/Kconfig.stm32f4 index 78a2a5ca49befc..6782d26c766c9f 100644 --- a/drivers/adc/Kconfig.stm32f4 +++ b/drivers/adc/Kconfig.stm32f4 @@ -14,6 +14,14 @@ menuconfig ADC_STM32F4 select USE_STM32_HAL_ADC select USE_STM32_HAL_ADC_EX select USE_STM32_HAL_CORTEX + select USE_STM32_HAL_UART + select USE_STM32_HAL_DFSDM + select USE_STM32_HAL_DFSDM_EX + select USE_STM32_HAL_DMA + select USE_STM32_HAL_DMA_EX + select USE_STM32_HAL_RCC + select USE_STM32_HAL_RCC_EX + help Enable the driver implementation for the stm32f4xx ADC diff --git a/drivers/adc/adc_stm32f4.c b/drivers/adc/adc_stm32f4.c index 981dc35ec04b6c..9837032e1d1a17 100644 --- a/drivers/adc/adc_stm32f4.c +++ b/drivers/adc/adc_stm32f4.c @@ -1,7 +1,5 @@ -/* adc_dw.c - Designware ADC driver */ - /* - * Copyright (c) 2015 Intel Corporation + * Copyright (c) 2018 Kokoon Technology Limited * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,6 +25,35 @@ #include "adc_stm32f4.h" +typedef struct adc_stm32f4_control { + int initFlag; + int isrConnectedFlag; + struct k_sem adcReadSem; + struct adc_drvData * actDrv; + struct k_msgq adcVals; + uint16_t adcValBuff[adcChannel_max]; +} adc_stm32f4_control_t; + + +static adc_stm32f4_control_t ADCcontrol = { + .initFlag = 0, + .isrConnectedFlag = 0, + .actDrv = NULL +}; + +ISR_DIRECT_DECLARE(ADC_IRQHandler) +{ + HAL_ADC_IRQHandler(&ADCcontrol.actDrv->hadc); + ISR_DIRECT_PM(); /* PM done after servicing interrupt for best latency */ + return 1; /* We should check if scheduling decision should be made */ +} + +void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { + uint16_t v; + v = (uint16_t) HAL_ADC_GetValue(hadc); + k_msgq_put(&ADCcontrol.adcVals, &v, K_NO_WAIT); +} + #define ADC_STM32F4_SETBITMASK(bit) (1 << (bit)) static void adc_stm32f4_enable(struct device *dev) @@ -39,47 +66,54 @@ static void adc_stm32f4_enable(struct device *dev) static void adc_stm32f4_disable(struct device *dev) { const struct adc_config *config = dev->config->config_info; + struct adc_drvData *drvData = dev->driver_data; SYS_LOG_DBG("adc%u disable", (unsigned int)config->adcDevNum); - + HAL_ADC_Stop_IT(&drvData->hadc); } static int adc_stm32f4_read(struct device *dev, struct adc_seq_table *seq_tbl) { struct adc_drvData *drvData = dev->driver_data; const struct adc_config *config = dev->config->config_info; - uint16_t val; + adc_channel_index_t i; uint32_t activeChannels; - int rc; struct adc_seq_entry * pE; + uint16_t val; + int rc; - SYS_LOG_DBG("start adc%u conversion", (unsigned int)config->adcDevNum); + rc = stm32adcError_None; + SYS_LOG_DBG("adc%u conversion", (unsigned int)config->adcDevNum); + k_sem_take(&ADCcontrol.adcReadSem, K_FOREVER); + ADCcontrol.actDrv = drvData; // ok let's read for once the values - HAL_ADC_Start(&drvData->hadc); - // let's iterate through the sequence table + HAL_ADC_Start_IT(&drvData->hadc); pE = seq_tbl->entries; activeChannels = config->activeChannels; i = adcChannel_0; - rc = stm32adcError_None; while(activeChannels) { if(activeChannels & 0x1) { - if (HAL_ADC_PollForConversion(&drvData->hadc, 100) == HAL_OK) { - val = HAL_ADC_GetValue(&drvData->hadc); + if (!k_msgq_get(&ADCcontrol.adcVals, &val,ADC_STM32_ADC_TIMEOUT_US)) { + *((uint16_t *) pE->buffer) = val; + pE++; } else { - rc = stm32adcError_adcHALerror; - val = 0; + rc = stm32adcError_ADCtimeout; + *((uint16_t *) pE->buffer) = 0; + goto error; } - *((uint16_t *) pE->buffer) = val; - pE++; } activeChannels >>= 1; i++; } - HAL_ADC_Stop(&drvData->hadc); - - SYS_LOG_DBG("end adc%u conversion with rc=%i", (unsigned int)config->adcDevNum, rc); + HAL_ADC_Stop_IT(&drvData->hadc); + k_sem_give(&ADCcontrol.adcReadSem); + return rc; +error: + HAL_ADC_Stop_IT(&drvData->hadc); + k_msgq_purge(&ADCcontrol.adcVals); + k_sem_give(&ADCcontrol.adcReadSem); return rc; } @@ -228,6 +262,22 @@ int adc_stm32f4_init(struct device *dev) SYS_LOG_INF("init adc%u", (unsigned int)config->adcDevNum); + // init adc control structure + if (!ADCcontrol.initFlag) { + k_sem_init(&ADCcontrol.adcReadSem, 0, 1); + k_sem_give(&ADCcontrol.adcReadSem); + k_msgq_init(&ADCcontrol.adcVals, (char *)ADCcontrol.adcValBuff, sizeof(uint16_t), sizeof(ADCcontrol.adcValBuff)/sizeof(uint16_t)); + ADCcontrol.actDrv = NULL; + ADCcontrol.isrConnectedFlag = 0; + ADCcontrol.initFlag = 1; + } + + if(!ADCcontrol.isrConnectedFlag) { + IRQ_DIRECT_CONNECT(ADC_IRQn, 0, ADC_IRQHandler, 0); + irq_enable(ADC_IRQn); + ADCcontrol.isrConnectedFlag = 1; + } + switch(config->adcDevNum) { #ifdef CONFIG_ADC_0 case 0: @@ -256,7 +306,7 @@ int adc_stm32f4_init(struct device *dev) drvData->hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; drvData->hadc.Init.Resolution = ADC_RESOLUTION_12B; drvData->hadc.Init.ScanConvMode = ENABLE; - drvData->hadc.Init.ContinuousConvMode = ENABLE; + drvData->hadc.Init.ContinuousConvMode = DISABLE; drvData->hadc.Init.DiscontinuousConvMode = DISABLE; drvData->hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; drvData->hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; @@ -264,7 +314,6 @@ int adc_stm32f4_init(struct device *dev) drvData->hadc.Init.DMAContinuousRequests = DISABLE; drvData->hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; drvData->hadc.Init.NbrOfConversion = 0; - activeChannels = config->activeChannels; while(activeChannels) { if(activeChannels & 1) drvData->hadc.Init.NbrOfConversion++; @@ -295,6 +344,8 @@ int adc_stm32f4_init(struct device *dev) activeChannels >>= 1; i++; } + + return stm32adcError_None; } diff --git a/drivers/adc/adc_stm32f4.h b/drivers/adc/adc_stm32f4.h index b145dde480f00a..16844b4e25e96e 100644 --- a/drivers/adc/adc_stm32f4.h +++ b/drivers/adc/adc_stm32f4.h @@ -1,18 +1,21 @@ -// -// STM32F4xx HAL ADC driver -// -// author: Stefan Jaritz -// 2018 Kokoon Technology Limited +/* + * Copyright (c) 2018 Kokoon Technology Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef STM32F4_ADC_H_ #define STM32F4_ADC_H_ #include #include +#include #ifdef __cplusplus extern "C" { #endif +// set timeout to 1sec +#define ADC_STM32_ADC_TIMEOUT_US (USEC_PER_SEC * 1000) //! type and enum for channel ids typedef enum adcChannels { @@ -47,6 +50,7 @@ enum stm32adcErrors { stm32adcError_adcHALerror, stm32adcError_drvError = 100, stm32adcError_configChannel, + stm32adcError_ADCtimeout, stm32adcError_UnknownADCunit, }; @@ -62,7 +66,6 @@ typedef struct adc_drvData { ADC_HandleTypeDef hadc; } adc_drvData_t; - // // @brief ADC Initialization function. //