diff --git a/targets/TARGET_STM/TARGET_STM32F4/analogout_device.c b/targets/TARGET_STM/TARGET_STM32F4/analogout_device.c index f3cd5c6779..485c27d46a 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/analogout_device.c +++ b/targets/TARGET_STM/TARGET_STM32F4/analogout_device.c @@ -23,6 +23,12 @@ #include "stm32f4xx_hal.h" #include "PeripheralPins.h" +// These variables are used for the "free" function +static int dac_channel1_used = 0; +#if defined(DAC_CHANNEL_2) +static int dac_channel2_used = 0; +#endif + #if STATIC_PINMAP_READY #define ANALOGOUT_INIT_DIRECT analogout_init_direct void analogout_init_direct(dac_t *obj, const PinMap *pinmap) @@ -62,6 +68,9 @@ static void _analogout_init_direct(dac_t *obj, const PinMap *pinmap) pin_function(pinmap->pin, pinmap->function); pin_mode(pinmap->pin, PullNone); + // Save the pin for future use + obj->pin = pinmap->pin; + __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_DAC_CLK_ENABLE(); @@ -80,6 +89,14 @@ static void _analogout_init_direct(dac_t *obj, const PinMap *pinmap) error("HAL_DAC_ConfigChannel failed"); } + if (obj->channel == DAC_CHANNEL_1) { + dac_channel1_used = 1; + } +#if defined(DAC_CHANNEL_2) + if (obj->channel == DAC_CHANNEL_2) { + dac_channel2_used = 1; + } +#endif analogout_write_u16(obj, 0); HAL_DAC_Start(&obj->handle, obj->channel); } @@ -96,6 +113,28 @@ void analogout_init(dac_t *obj, PinName pin) void analogout_free(dac_t *obj) { + if (obj->channel == DAC_CHANNEL_1) { + dac_channel1_used = 0; + } +#if defined(DAC_CHANNEL_2) + if (obj->channel == DAC_CHANNEL_2) { + dac_channel2_used = 0; + } +#endif + + if ((dac_channel1_used == 0) +#if defined(DAC_CHANNEL_2) + && (dac_channel2_used == 0) +#endif + ) { + // Reset DAC and disable clock + __HAL_RCC_DAC_FORCE_RESET(); + __HAL_RCC_DAC_RELEASE_RESET(); + __HAL_RCC_DAC_CLK_DISABLE(); + + // Configure GPIO back to reset value + pin_function(obj->pin, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); + } } const PinMap *analogout_pinmap() diff --git a/targets/TARGET_STM/TARGET_STM32F4/objects.h b/targets/TARGET_STM/TARGET_STM32F4/objects.h index be2f3b3a31..f9b991d183 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/objects.h +++ b/targets/TARGET_STM/TARGET_STM32F4/objects.h @@ -141,6 +141,7 @@ struct analogin_s { #if DEVICE_ANALOGOUT struct dac_s { DACName dac; + PinName pin; uint32_t channel; DAC_HandleTypeDef handle; }; diff --git a/targets/TARGET_STM/TARGET_STM32F7/analogout_device.c b/targets/TARGET_STM/TARGET_STM32F7/analogout_device.c index 99425e9a7f..fba0379d78 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/analogout_device.c +++ b/targets/TARGET_STM/TARGET_STM32F7/analogout_device.c @@ -35,6 +35,12 @@ #include "stm32f7xx_hal.h" #include "PeripheralPins.h" +// These variables are used for the "free" function +static int channel1_used = 0; +#if defined(DAC_CHANNEL_2) +static int channel2_used = 0; +#endif + void analogout_init(dac_t *obj, PinName pin) { DAC_ChannelConfTypeDef sConfig = {0}; @@ -67,6 +73,9 @@ void analogout_init(dac_t *obj, PinName pin) // Configure GPIO pinmap_pinout(pin, PinMap_DAC); + // Save the pin for future use + obj->pin = pin; + __GPIOA_CLK_ENABLE(); __DAC_CLK_ENABLE(); @@ -85,12 +94,41 @@ void analogout_init(dac_t *obj, PinName pin) error("HAL_DAC_ConfigChannel failed"); } + if (obj->channel == DAC_CHANNEL_1) { + channel1_used = 1; + } +#if defined(DAC_CHANNEL_2) + if (obj->channel == DAC_CHANNEL_2) { + channel2_used = 1; + } +#endif analogout_write_u16(obj, 0); HAL_DAC_Start(&obj->handle, obj->channel); } void analogout_free(dac_t *obj) { + if (obj->channel == DAC_CHANNEL_1) { + channel1_used = 0; + } +#if defined(DAC_CHANNEL_2) + if (obj->channel == DAC_CHANNEL_2) { + channel2_used = 0; + } +#endif + if ((channel1_used == 0) +#if defined(DAC_CHANNEL_2) + && (channel2_used == 0) +#endif + ) { + // Reset DAC and disable clock + __HAL_RCC_DAC_FORCE_RESET(); + __HAL_RCC_DAC_RELEASE_RESET(); + __HAL_RCC_DAC_CLK_DISABLE(); + + // Configure GPIO back to reset value + pin_function(obj->pin, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); + } } const PinMap *analogout_pinmap() diff --git a/targets/TARGET_STM/TARGET_STM32H7/analogout_device.c b/targets/TARGET_STM/TARGET_STM32H7/analogout_device.c index e375e16a8a..b66233564a 100644 --- a/targets/TARGET_STM/TARGET_STM32H7/analogout_device.c +++ b/targets/TARGET_STM/TARGET_STM32H7/analogout_device.c @@ -23,6 +23,12 @@ #include "stm32h7xx_hal.h" #include "PeripheralPins.h" +// These variables are used for the "free" function +static int channel1_used = 0; +#if defined(DAC_CHANNEL_2) +static int channel2_used = 0; +#endif + void analogout_init(dac_t *obj, PinName pin) { DAC_ChannelConfTypeDef sConfig = {0}; @@ -55,6 +61,9 @@ void analogout_init(dac_t *obj, PinName pin) // Configure GPIO pinmap_pinout(pin, PinMap_DAC); + // Save the pin for future use + obj->pin = pin; + __GPIOA_CLK_ENABLE(); if (obj->dac == DAC_1) { @@ -80,12 +89,50 @@ void analogout_init(dac_t *obj, PinName pin) error("HAL_DAC_ConfigChannel failed"); } + if (obj->channel == DAC_CHANNEL_1) { + channel1_used = 1; + } +#if defined(DAC_CHANNEL_2) + if (obj->channel == DAC_CHANNEL_2) { + channel2_used = 1; + } +#endif analogout_write_u16(obj, 0); HAL_DAC_Start(&obj->handle, obj->channel); } void analogout_free(dac_t *obj) { + if (obj->channel == DAC_CHANNEL_1) { + channel1_used = 0; + } +#if defined(DAC_CHANNEL_2) + if (obj->channel == DAC_CHANNEL_2) { + channel2_used = 0; + } +#endif + + if ((channel1_used == 0) +#if defined(DAC_CHANNEL_2) + && (channel2_used == 0) +#endif + ) { + // Reset DAC and disable clock + __HAL_RCC_DAC12_FORCE_RESET(); + __HAL_RCC_DAC12_RELEASE_RESET(); + __HAL_RCC_DAC12_CLK_DISABLE(); + } + +#if defined(DAC2) + if (obj->dac == DAC_2) { + __HAL_RCC_DAC2_FORCE_RESET(); + __HAL_RCC_DAC2_RELEASE_RESET(); + __HAL_RCC_DAC2_CLK_DISABLE(); + } +#endif + + // Configure GPIO back to reset value + pin_function(obj->pin, STM_PIN_DATA(STM_MODE_ANALOG, GPIO_NOPULL, 0)); } const PinMap *analogout_pinmap()