From a89cd8645400edf32ae99bce4b883cc9e5306f66 Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Fri, 16 Oct 2015 22:37:54 +0000 Subject: [PATCH] stm32f0/f3: adc: extract beginnings of common v2 periph The f0, f30x and l0 have a very similar "v2" adc peripheral. Start extracting out some of the common code, and fix the glaring bug in adc_power_down that was affecting them both. This is not intended to be a fully comprehensive extraction, just the first easy steps. --- .../libopencm3/stm32/common/adc_common_v2.h | 54 ++++++++ include/libopencm3/stm32/f0/adc.h | 4 +- include/libopencm3/stm32/f3/adc.h | 4 +- lib/stm32/common/adc_common_v2.c | 115 ++++++++++++++++++ lib/stm32/f0/Makefile | 1 + lib/stm32/f0/adc.c | 28 ----- lib/stm32/f3/Makefile | 1 + lib/stm32/f3/adc.c | 31 ----- 8 files changed, 175 insertions(+), 63 deletions(-) create mode 100644 include/libopencm3/stm32/common/adc_common_v2.h create mode 100644 lib/stm32/common/adc_common_v2.c diff --git a/include/libopencm3/stm32/common/adc_common_v2.h b/include/libopencm3/stm32/common/adc_common_v2.h new file mode 100644 index 00000000..9d6a960d --- /dev/null +++ b/include/libopencm3/stm32/common/adc_common_v2.h @@ -0,0 +1,54 @@ +/** @addtogroup adc_defines + +@author @htmlonly © @endhtmlonly 2015 Karl Palsson + + */ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2015 Karl Palsson + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/**@{*/ + +/* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY, BUT ONLY VIA ADC.H +The order of header inclusion is important. adc.h includes the device +specific memorymap.h header before including this header file.*/ + +/** @cond */ +#ifdef LIBOPENCM3_ADC_H +/** @endcond */ +#ifndef LIBOPENCM3_ADC_COMMON_V2_H +#define LIBOPENCM3_ADC_COMMON_V2_H + + +/* --- Function prototypes ------------------------------------------------- */ + +BEGIN_DECLS + +void adc_power_on_async(uint32_t adc); +void adc_power_on(uint32_t adc); +bool adc_is_power_on(uint32_t adc); +void adc_power_off_async(uint32_t adc); +void adc_power_off(uint32_t adc); +bool adc_is_power_off(uint32_t adc); + +END_DECLS + +#endif +#endif /* LIBOPENCM3_ADC_H */ +/**@}*/ diff --git a/include/libopencm3/stm32/f0/adc.h b/include/libopencm3/stm32/f0/adc.h index c6bd43aa..5e4cc877 100644 --- a/include/libopencm3/stm32/f0/adc.h +++ b/include/libopencm3/stm32/f0/adc.h @@ -33,6 +33,8 @@ #ifndef LIBOPENCM3_ADC_H #define LIBOPENCM3_ADC_H +#include + /*****************************************************************************/ /* Module definitions */ /*****************************************************************************/ @@ -305,8 +307,6 @@ void adc_enable_eoc_interrupt(uint32_t adc); void adc_disable_eoc_interrupt(uint32_t adc); /* Basic configuration */ -void adc_power_off(uint32_t adc); -void adc_power_on(uint32_t adc); void adc_set_clk_source(uint32_t adc, uint32_t source); void adc_set_regular_sequence(uint32_t adc, uint8_t length, uint8_t channel[]); void adc_set_sample_time_on_all_channels(uint32_t adc, uint8_t time); diff --git a/include/libopencm3/stm32/f3/adc.h b/include/libopencm3/stm32/f3/adc.h index 2524e6a5..048275bc 100644 --- a/include/libopencm3/stm32/f3/adc.h +++ b/include/libopencm3/stm32/f3/adc.h @@ -34,6 +34,8 @@ #ifndef LIBOPENCM3_ADC_H #define LIBOPENCM3_ADC_H +#include + #define ADC1 ADC1_BASE #define ADC2 ADC2_BASE #define ADC3 ADC3_BASE @@ -863,8 +865,6 @@ BEGIN_DECLS -void adc_power_on(uint32_t adc); -void adc_power_off(uint32_t adc); void adc_enable_analog_watchdog_regular(uint32_t adc); void adc_disable_analog_watchdog_regular(uint32_t adc); void adc_enable_analog_watchdog_injected(uint32_t adc); diff --git a/lib/stm32/common/adc_common_v2.c b/lib/stm32/common/adc_common_v2.c new file mode 100644 index 00000000..fc7f8b85 --- /dev/null +++ b/lib/stm32/common/adc_common_v2.c @@ -0,0 +1,115 @@ +/** @addtogroup adc_file + +@author @htmlonly © @endhtmlonly +2015 Karl Palsson + +This library supports one style of the Analog to Digital Conversion System in +the STM32 series of ARM Cortex Microcontrollers by ST Microelectronics. + +The style of ADC Peripheral supported by this code is found in the F0, L0 and +F30x series devices (at the time of writing) + +LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2015 Karl Palsson + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/**@{*/ + +#include + +/** + * Turn on the ADC (async) + * @sa adc_wait_power_on + * @param adc ADC Block register address base @ref adc_reg_base + */ +void adc_power_on_async(uint32_t adc) +{ + ADC_CR(adc) |= ADC_CR_ADEN; +} + +/** + * Is the ADC powered up and ready? + * @sa adc_power_on_async + * @param adc ADC Block register address base @ref adc_reg_base + * @return true if adc is ready for use + */ +bool adc_is_power_on(uint32_t adc) +{ + return (ADC_ISR(adc) & ADC_ISR_ADRDY); +} + +/** + * Turn on the ADC + * @sa adc_power_on_async + * @param adc ADC Block register address base @ref adc_reg_base + */ +void adc_power_on(uint32_t adc) +{ + adc_power_on_async(adc); + while (!adc_is_power_on(adc)); +} + +/** + * Turn off the ADC (async) + * This will actually block if it needs to turn off a currently running + * conversion, as per ref man. (Handles injected on hardware that supports + * injected conversions. + * @sa adc_wait_power_off + * @param adc ADC Block register address base @ref adc_reg_base + */ +void adc_power_off_async(uint32_t adc) +{ + uint32_t checks = ADC_CR_ADSTART; + uint32_t stops = ADC_CR_ADSTP; +#if defined (ADC_CR_JADSTART) + checks |= ADC_CR_JADSTART; + stops |= ADC_CR_JADSTP; +#endif + if (ADC_CR(adc) & checks) { + ADC_CR(adc) |= stops; + while (ADC_CR(adc) & checks); + } + ADC_CR(adc) |= ADC_CR_ADDIS; +} + +/** + * Is the ADC powered down? + * @sa adc_power_off_async + * @param adc ADC Block register address base @ref adc_reg_base + */ +bool adc_is_power_off(uint32_t adc) +{ + return (!(ADC_CR(adc) & ADC_CR_ADEN)); +} + +/** + * Turn off the ADC + * This will actually block if it needs to turn off a currently running + * conversion, as per ref man. + * @sa adc_power_off_async + * @param adc ADC Block register address base @ref adc_reg_base + */ +void adc_power_off(uint32_t adc) +{ + adc_power_off_async(adc); + while (!adc_is_power_off(adc)); +} + diff --git a/lib/stm32/f0/Makefile b/lib/stm32/f0/Makefile index f5841045..843d66e9 100644 --- a/lib/stm32/f0/Makefile +++ b/lib/stm32/f0/Makefile @@ -43,6 +43,7 @@ OBJS += gpio_common_all.o gpio_common_f0234.o crc_common_all.o \ dma_common_l1f013.o exti_common_all.o spi_common_all.o \ spi_common_f03.o flash_common_f01.o dac_common_all.o \ timer_common_all.o rcc_common_all.o +OBJS += adc_common_v2.o OBJS += crs_common_all.o OBJS += usb.o usb_control.o usb_standard.o diff --git a/lib/stm32/f0/adc.c b/lib/stm32/f0/adc.c index ec2c7950..949443ed 100644 --- a/lib/stm32/f0/adc.c +++ b/lib/stm32/f0/adc.c @@ -461,34 +461,6 @@ void adc_disable_eoc_interrupt(uint32_t adc) * *@{*/ -/*---------------------------------------------------------------------------*/ -/** @brief ADC Power Off - * - * Turn off the ADC to reduce power consumption to a few microamps. - * - * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base) - */ - -void adc_power_off(uint32_t adc) -{ - ADC_CR(adc) &= ~ADC_CR_ADEN; -} - -/*---------------------------------------------------------------------------*/ -/** @brief ADC Power On - * - * If the ADC is in power-down mode then it is powered up. The application - * needs to wait a time of about 3 microseconds for stabilization before using - * the ADC. If the ADC is already on this function call will have no effect. - * - * @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base) - */ - -void adc_power_on(uint32_t adc) -{ - ADC_CR(adc) |= ADC_CR_ADEN; -} - /*---------------------------------------------------------------------------*/ /** @brief ADC Set Clock Prescale * diff --git a/lib/stm32/f3/Makefile b/lib/stm32/f3/Makefile index b3b134c7..4e1f7192 100644 --- a/lib/stm32/f3/Makefile +++ b/lib/stm32/f3/Makefile @@ -43,6 +43,7 @@ OBJS += gpio_common_all.o gpio_common_f0234.o \ iwdg_common_all.o spi_common_all.o dma_common_l1f013.o\ timer_common_all.o timer_common_f234.o flash_common_f234.o \ flash.o exti_common_all.o rcc_common_all.o spi_common_f03.o +OBJS += adc_common_v2.o OBJS += usb.o usb_control.o usb_standard.o OBJS += st_usbfs_core.o st_usbfs_v1.o diff --git a/lib/stm32/f3/adc.c b/lib/stm32/f3/adc.c index d851bd40..e8d7f82d 100644 --- a/lib/stm32/f3/adc.c +++ b/lib/stm32/f3/adc.c @@ -88,20 +88,6 @@ /**@{*/ -/*---------------------------------------------------------------------------*/ -/** @brief ADC Off - * - * Turn off the ADC to reduce power consumption to a few microamps. - * - * @param[in] adc Unsigned int32. ADC block register address base @ref - * adc_reg_base -*/ - -void adc_power_off(uint32_t adc) -{ - ADC_CR(adc) &= ~ADC_CR_ADEN; -} - /*---------------------------------------------------------------------------*/ /** @brief ADC Enable Analog Watchdog for Regular Conversions * @@ -905,23 +891,6 @@ void adc_set_injected_offset(uint32_t adc, uint8_t reg, uint32_t offset) } } -/*---------------------------------------------------------------------------*/ -/** @brief ADC Power On - * - * If the ADC is in power-down mode then it is powered up. The application - * needs to wait a time of about 3 microseconds for stabilization before using - * the ADC. If the ADC is already on this function call will have no effect. - * - * @param[in] adc Unsigned int32. ADC block register address base @ref - * adc_reg_base - */ - -void adc_power_on(uint32_t adc) -{ - ADC_CR(adc) |= ADC_CR_ADEN; -} - - /*---------------------------------------------------------------------------*/ /** @brief ADC Set Clock Prescale *