From 21468a69ca2e7ff9a5c7ffc03c608a24f1412d64 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 20 Mar 2012 17:44:34 -0400 Subject: [FIXME] Resurrect boards.cpp for F2 and F1. FIXME: - F1 support currently appears to be failing in start_c.c, for some unknown reason. This will need to get sorted out later. Add a new wirish namespace, and a sub-namespace wirish::priv::. Put a bunch of board setup routines in this namespace, and declare them in new wirish/boards_private.h. boards.cpp uses this to perform initialization tasks in a portable way, with two new boards_setup.cpp files under wirish/stm32f1 and wirish/stm32f2 handling the series-specific details. Signed-off-by: Marti Bolivar --- wirish/stm32f2/boards_setup.cpp | 75 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 wirish/stm32f2/boards_setup.cpp (limited to 'wirish/stm32f2') diff --git a/wirish/stm32f2/boards_setup.cpp b/wirish/stm32f2/boards_setup.cpp new file mode 100644 index 0000000..b3c690c --- /dev/null +++ b/wirish/stm32f2/boards_setup.cpp @@ -0,0 +1,75 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file wirish/stm32f2/boards_setup.cpp + * @author Marti Bolivar + * @brief STM32F2 chip setup. + */ + +#include +#include + +#define PLL_Q 5 +#define PLL_P 2 +#define PLL_N 240 +#define PLL_M 25 +static stm32f2_rcc_pll_data pll_data = {PLL_Q, PLL_P, PLL_N, PLL_M}; + +namespace wirish { + namespace priv { + rcc_pll_cfg board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; + + void board_reset_pll(void) { + // Set PLLCFGR to its reset value. + RCC_BASE->PLLCFGR = 0x24003010; // FIXME lose the magic number. + } + + void board_setup_clock_prescalers(void) { + rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1); + rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_4); + rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_2); + } + + void board_setup_gpio(void) { + gpio_init_all(); + } + + void board_setup_adc(void) { + // TODO + } + + void board_setup_timers(void) { + // TODO + } + + void board_setup_usb(void) { + // TODO + } + + } +} + -- cgit v1.2.3 From 28825b6a2f66b0329229185eb9cbd9004fae4b1b Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Mon, 26 Mar 2012 22:17:47 -0400 Subject: Resurrect ADC support. Standard refactoring: add series headers for F1 and F2, along with series adc.c files. There are some issues relating to adc_extsel_event to hammer out later, but this will do for now. We also add some new portability interfaces to libmaple/adc.h in order for Wirish to use the same code to initialize the ADCs at init() time. As usual, F1 is untested. Signed-off-by: Marti Bolivar --- libmaple/adc.c | 74 +------- libmaple/include/libmaple/adc.h | 175 +++++++----------- libmaple/rules.mk | 4 +- libmaple/stm32f1/adc.c | 110 +++++++++++ libmaple/stm32f1/include/series/adc.h | 254 ++++++++++++++++++++++++++ libmaple/stm32f1/rules.mk | 3 +- libmaple/stm32f2/adc.c | 84 +++++++++ libmaple/stm32f2/include/series/adc.h | 331 ++++++++++++++++++++++++++++++++++ libmaple/stm32f2/rules.mk | 1 + wirish/boards.cpp | 15 +- wirish/boards_private.h | 12 +- wirish/stm32f1/boards_setup.cpp | 39 ++-- wirish/stm32f2/boards_setup.cpp | 32 +++- 13 files changed, 920 insertions(+), 214 deletions(-) create mode 100644 libmaple/stm32f1/adc.c create mode 100644 libmaple/stm32f1/include/series/adc.h create mode 100644 libmaple/stm32f2/adc.c create mode 100644 libmaple/stm32f2/include/series/adc.h (limited to 'wirish/stm32f2') diff --git a/libmaple/adc.c b/libmaple/adc.c index 40369e9..acce923 100644 --- a/libmaple/adc.c +++ b/libmaple/adc.c @@ -25,44 +25,15 @@ *****************************************************************************/ /** - * @file adc.c - * + * @file libmaple/adc.c + * @author Marti Bolivar , + * Perry Hung * @brief Analog to digital converter routines - * - * IMPORTANT: maximum external impedance must be below 0.4kOhms for 1.5 - * sample conversion time. - * - * At 55.5 cycles/sample, the external input impedance < 50kOhms. - * - * See STM32 manual RM0008 for how to calculate this. */ +#include #include #include -#include - -static adc_dev adc1 = { - .regs = ADC1_BASE, - .clk_id = RCC_ADC1 -}; -/** ADC1 device. */ -const adc_dev *ADC1 = &adc1; - -static adc_dev adc2 = { - .regs = ADC2_BASE, - .clk_id = RCC_ADC2 -}; -/** ADC2 device. */ -const adc_dev *ADC2 = &adc2; - -#ifdef STM32_HIGH_DENSITY -adc_dev adc3 = { - .regs = ADC3_BASE, - .clk_id = RCC_ADC3 -}; -/** ADC3 device. */ -const adc_dev *ADC3 = &adc3; -#endif /** * @brief Initialize an ADC peripheral. @@ -91,20 +62,10 @@ void adc_set_extsel(const adc_dev *dev, adc_extsel_event event) { } /** - * @brief Call a function on all ADC devices. - * @param fn Function to call on each ADC device. - */ -void adc_foreach(void (*fn)(const adc_dev*)) { - fn(ADC1); - fn(ADC2); -#ifdef STM32_HIGH_DENSITY - fn(ADC3); -#endif -} - -/** - * @brief Turn the given sample rate into values for ADC_SMPRx. Don't - * call this during conversion. + * @brief Set the sample rate for all channels on an ADC device. + * + * Don't call this during conversion. + * * @param dev adc device * @param smp_rate sample rate to set * @see adc_smp_rate @@ -126,26 +87,9 @@ void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate) { dev->regs->SMPR2 = adc_smpr2_val; } -/** - * @brief Calibrate an ADC peripheral - * @param dev adc device - */ -void adc_calibrate(const adc_dev *dev) { - __io uint32 *rstcal_bit = bb_perip(&(dev->regs->CR2), 3); - __io uint32 *cal_bit = bb_perip(&(dev->regs->CR2), 2); - - *rstcal_bit = 1; - while (*rstcal_bit) - ; - - *cal_bit = 1; - while (*cal_bit) - ; -} - /** * @brief Perform a single synchronous software triggered conversion on a - * channel. + * channel. * @param dev ADC device to use for reading. * @param channel channel to convert * @return conversion result diff --git a/libmaple/include/libmaple/adc.h b/libmaple/include/libmaple/adc.h index d531d00..be29676 100644 --- a/libmaple/include/libmaple/adc.h +++ b/libmaple/include/libmaple/adc.h @@ -1,6 +1,7 @@ /****************************************************************************** * The MIT License * + * Copyright (c) 2012 LeafLabs, LLC. * Copyright (c) 2010 Perry Hung. * * Permission is hereby granted, free of charge, to any person @@ -25,9 +26,10 @@ *****************************************************************************/ /** - * @file adc.h - * - * @brief Analog-to-Digital Conversion (ADC) header. + * @file libmaple/adc.h + * @author Marti Bolivar , + * Perry Hung + * @brief Analog-to-Digital Conversion (ADC) header. */ #ifndef _LIBMAPLE_ADC_H_ @@ -40,6 +42,12 @@ extern "C"{ #include #include #include +/* We include the series header below, after defining the register map + * and device structs. */ + +/* + * Register map + */ /** ADC register map type. */ typedef struct adc_reg_map { @@ -71,24 +79,30 @@ typedef struct adc_dev { rcc_clk_id clk_id; /**< RCC clock information */ } adc_dev; -extern const adc_dev *ADC1; -extern const adc_dev *ADC2; -#ifdef STM32_HIGH_DENSITY -extern const adc_dev *ADC3; -#endif - -/* - * Register map base pointers +/* Pull in the series header (which may need the above struct + * definitions). + * + * IMPORTANT: The series header must define the following: + * + * - enum adc_extsel_event (and typedef to adc_extsel_event): One per + * external event used to trigger start of conversion of a regular + * group. If two different series support the same event as a + * trigger, they must use the same token for the enumerator for that + * event. (The value of the enumerator is of course allowed to be + * different). + * + * - enum adc_smp_rate (and typedef to adc_smp_rate): One per + * available sampling time. These must be in the form ADC_SMPR_X_Y + * for X.Y cycles (e.g. ADC_SMPR_1_5 means 1.5 cycles), or + * ADC_SMPR_X for X cycles (e.g. ADC_SMPR_3 means 3 cycles). + * + * - enum adc_prescaler (and typedef): One per available prescaler, + * suitable for adc_set_prescaler. Series which have the same + * prescaler dividers (e.g. STM32F1 and STM32F2 both divide PCLK2 by + * 2, 4, 6, or 8) must provide the same tokens as enumerators, for + * portability. */ - -/** ADC1 register map base pointer. */ -#define ADC1_BASE ((struct adc_reg_map*)0x40012400) -/** ADC2 register map base pointer. */ -#define ADC2_BASE ((struct adc_reg_map*)0x40012800) -#ifdef STM32_HIGH_DENSITY -/** ADC3 register map base pointer. */ -#define ADC3_BASE ((struct adc_reg_map*)0x40013C00) -#endif +#include /* * Register bit definitions @@ -136,31 +150,9 @@ extern const adc_dev *ADC3; /* Control register 2 */ -#define ADC_CR2_ADON_BIT 0 -#define ADC_CR2_CONT_BIT 1 -#define ADC_CR2_CAL_BIT 2 -#define ADC_CR2_RSTCAL_BIT 3 -#define ADC_CR2_DMA_BIT 8 -#define ADC_CR2_ALIGN_BIT 11 -#define ADC_CR2_JEXTTRIG_BIT 15 -#define ADC_CR2_EXTTRIG_BIT 20 -#define ADC_CR2_JSWSTART_BIT 21 -#define ADC_CR2_SWSTART_BIT 22 -#define ADC_CR2_TSEREFE_BIT 23 - -#define ADC_CR2_ADON BIT(ADC_CR2_ADON_BIT) -#define ADC_CR2_CONT BIT(ADC_CR2_CONT_BIT) -#define ADC_CR2_CAL BIT(ADC_CR2_CAL_BIT) -#define ADC_CR2_RSTCAL BIT(ADC_CR2_RSTCAL_BIT) -#define ADC_CR2_DMA BIT(ADC_CR2_DMA_BIT) -#define ADC_CR2_ALIGN BIT(ADC_CR2_ALIGN_BIT) -#define ADC_CR2_JEXTSEL (0x7000) -#define ADC_CR2_JEXTTRIG BIT(ADC_CR2_JEXTTRIG_BIT) -#define ADC_CR2_EXTSEL (0xE0000) -#define ADC_CR2_EXTTRIG BIT(ADC_CR2_EXTTRIG_BIT) -#define ADC_CR2_JSWSTART BIT(ADC_CR2_JSWSTART_BIT) -#define ADC_CR2_SWSTART BIT(ADC_CR2_SWSTART_BIT) -#define ADC_CR2_TSEREFE BIT(ADC_CR2_TSEREFE_BIT) +/* Because this register varies significantly by series (e.g. some + * bits moved and others disappeared in the F1->F2 transition), its + * definitions are in the series headers. */ /* Sample time register 1 */ @@ -245,68 +237,47 @@ extern const adc_dev *ADC3; #define ADC_DR_ADC2DATA (0xFFFF << 16) #define ADC_DR_DATA 0xFFFF -void adc_init(const adc_dev *dev); +/* + * Routines + */ /** - * @brief External event selector for regular group conversion. - * @see adc_set_extsel + * @brief Set the ADC prescaler. + * + * This determines the ADC clock for all devices. */ -typedef enum adc_extsel_event { - ADC_ADC12_TIM1_CC1 = (0 << 17), /**< ADC1 and ADC2: Timer 1 CC1 event */ - ADC_ADC12_TIM1_CC2 = (1 << 17), /**< ADC1 and ADC2: Timer 1 CC2 event */ - ADC_ADC12_TIM1_CC3 = (2 << 17), /**< ADC1 and ADC2: Timer 1 CC3 event */ - ADC_ADC12_TIM2_CC2 = (3 << 17), /**< ADC1 and ADC2: Timer 2 CC2 event */ - ADC_ADC12_TIM3_TRGO = (4 << 17), /**< ADC1 and ADC2: Timer 3 TRGO event */ - ADC_ADC12_TIM4_CC4 = (5 << 17), /**< ADC1 and ADC2: Timer 4 CC4 event */ - ADC_ADC12_EXTI11 = (6 << 17), /**< ADC1 and ADC2: EXTI11 event */ -#ifdef STM32_HIGH_DENSITY - ADC_ADC12_TIM8_TRGO = (6 << 17), /**< ADC1 and ADC2: Timer 8 TRGO - event (high density only) */ -#endif - ADC_ADC12_SWSTART = (7 << 17), /**< ADC1 and ADC2: Software start */ -#ifdef STM32_HIGH_DENSITY - ADC_ADC3_TIM3_CC1 = (0 << 17), /**< ADC3: Timer 3 CC1 event - (high density only) */ - ADC_ADC3_TIM2_CC3 = (1 << 17), /**< ADC3: Timer 2 CC3 event - (high density only) */ - ADC_ADC3_TIM1_CC3 = (2 << 17), /**< ADC3: Timer 1 CC3 event - (high density only) */ - ADC_ADC3_TIM8_CC1 = (3 << 17), /**< ADC3: Timer 8 CC1 event - (high density only) */ - ADC_ADC3_TIM8_TRGO = (4 << 17), /**< ADC3: Timer 8 TRGO event - (high density only) */ - ADC_ADC3_TIM5_CC1 = (5 << 17), /**< ADC3: Timer 5 CC1 event - (high density only) */ - ADC_ADC3_TIM5_CC3 = (6 << 17), /**< ADC3: Timer 5 CC3 event - (high density only) */ - ADC_ADC3_SWSTART = (7 << 17), /**< ADC3: Software start (high - density only) */ -#endif - ADC_SWSTART = (7 << 17) /**< ADC1, ADC2, ADC3: Software start */ -} adc_extsel_event; +void adc_set_prescaler(adc_prescaler pre); +void adc_init(const adc_dev *dev); void adc_set_extsel(const adc_dev *dev, adc_extsel_event event); +void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate); +uint16 adc_read(const adc_dev *dev, uint8 channel); + +/** + * @brief Call a function on all ADC devices. + * @param fn Function to call on each ADC device. + */ void adc_foreach(void (*fn)(const adc_dev*)); /** - * @brief ADC sample times, in ADC clock cycles - * - * These control the amount of time spent sampling the input voltage. + * @brief Configure a GPIO pin for ADC conversion. + * @param gdev GPIO device to configure. + * @param bit Bit on gdev to configure for ADC conversion. */ -typedef enum { - ADC_SMPR_1_5, /**< 1.5 ADC cycles */ - ADC_SMPR_7_5, /**< 7.5 ADC cycles */ - ADC_SMPR_13_5, /**< 13.5 ADC cycles */ - ADC_SMPR_28_5, /**< 28.5 ADC cycles */ - ADC_SMPR_41_5, /**< 41.5 ADC cycles */ - ADC_SMPR_55_5, /**< 55.5 ADC cycles */ - ADC_SMPR_71_5, /**< 71.5 ADC cycles */ - ADC_SMPR_239_5 /**< 239.5 ADC cycles */ -} adc_smp_rate; +struct gpio_dev; +void adc_gpio_cfg(struct gpio_dev *gdev, uint8 bit); -void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate); -void adc_calibrate(const adc_dev *dev); -uint16 adc_read(const adc_dev *dev, uint8 channel); +/** + * @brief Enable an ADC and configure it for single conversion mode. + * + * This function performs any initialization necessary to allow the + * ADC device to perform a single synchronous regular software + * triggered conversion, using adc_read(). + * + * @param dev Device to enable. + * @see adc_read() + */ +void adc_enable_single_swstart(const adc_dev* dev); /** * @brief Set the regular channel sequence length. @@ -324,16 +295,6 @@ static inline void adc_set_reg_seqlen(const adc_dev *dev, uint8 length) { dev->regs->SQR1 = tmp; } -/** - * @brief Set external trigger conversion mode event for regular channels - * @param dev ADC device - * @param enable If 1, conversion on external events is enabled; if 0, - * disabled. - */ -static inline void adc_set_exttrig(const adc_dev *dev, uint8 enable) { - *bb_perip(&dev->regs->CR2, ADC_CR2_EXTTRIG_BIT) = !!enable; -} - /** * @brief Enable an adc peripheral * @param dev ADC device to enable diff --git a/libmaple/rules.mk b/libmaple/rules.mk index cc562ea..d118b16 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -11,7 +11,8 @@ LIBMAPLE_PRIVATE_INCLUDES := -I$(LIBMAPLE_PATH) CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets -cSRCS_$(d) := flash.c +cSRCS_$(d) := adc.c +cSRCS_$(d) += flash.c cSRCS_$(d) += gpio.c cSRCS_$(d) += iwdg.c cSRCS_$(d) += nvic.c @@ -23,7 +24,6 @@ cSRCS_$(d) += usart.c cSRCS_$(d) += usart_private.c cSRCS_$(d) += util.c # These still need to be ported to F2: -# cSRCS_$(d) += adc.c # cSRCS_$(d) += dac.c # cSRCS_$(d) += dma.c # cSRCS_$(d) += exti.c diff --git a/libmaple/stm32f1/adc.c b/libmaple/stm32f1/adc.c new file mode 100644 index 0000000..8242520 --- /dev/null +++ b/libmaple/stm32f1/adc.c @@ -0,0 +1,110 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/adc.c + * @brief STM32F1 ADC header. + */ + +#include +#include + +/* + * Devices + */ + +static adc_dev adc1 = { + .regs = ADC1_BASE, + .clk_id = RCC_ADC1 +}; +/** ADC1 device. */ +const adc_dev *ADC1 = &adc1; + +static adc_dev adc2 = { + .regs = ADC2_BASE, + .clk_id = RCC_ADC2 +}; +/** ADC2 device. */ +const adc_dev *ADC2 = &adc2; + +#ifdef STM32_HIGH_DENSITY +adc_dev adc3 = { + .regs = ADC3_BASE, + .clk_id = RCC_ADC3 +}; +/** ADC3 device. */ +const adc_dev *ADC3 = &adc3; +#endif + +/* + * STM32F1 routines + */ + +/** + * @brief Calibrate an ADC peripheral + * @param dev adc device + */ +void adc_calibrate(const adc_dev *dev) { + __io uint32 *rstcal_bit = bb_perip(&(dev->regs->CR2), 3); + __io uint32 *cal_bit = bb_perip(&(dev->regs->CR2), 2); + + *rstcal_bit = 1; + while (*rstcal_bit) + ; + + *cal_bit = 1; + while (*cal_bit) + ; +} + +/* + * Common routines + */ + +void adc_set_prescaler(adc_prescaler pre) { + rcc_set_prescaler(RCC_PRESCALER_ADC, (uint32)pre); +} + +void adc_foreach(void (*fn)(const adc_dev*)) { + fn(ADC1); + fn(ADC2); +#ifdef STM32_HIGH_DENSITY + fn(ADC3); +#endif +} + +void adc_gpio_cfg(gpio_dev *gdev, uint8 bit) { + gpio_set_mode(gdev, bit, GPIO_INPUT_ANALOG); +} + +void adc_enable_single_swstart(const adc_dev *dev) { + adc_init(dev); + adc_set_extsel(dev, ADC_SWSTART); + adc_set_exttrig(dev, 1); + adc_enable(dev); + adc_calibrate(dev); +} diff --git a/libmaple/stm32f1/include/series/adc.h b/libmaple/stm32f1/include/series/adc.h new file mode 100644 index 0000000..1798e55 --- /dev/null +++ b/libmaple/stm32f1/include/series/adc.h @@ -0,0 +1,254 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file stm32f1/include/series/adc.h + * @author Marti Bolivar , + * Perry Hung + * @brief STM32F1 ADC header. + */ + +#ifndef _LIBMAPLE_STM32F1_ADC_H_ +#define _LIBMAPLE_STM32F1_ADC_H_ + +#include /* For the prescalers */ + +/* + * Devices + */ + +extern const struct adc_dev *ADC1; +extern const struct adc_dev *ADC2; +#ifdef STM32_HIGH_DENSITY +extern const struct adc_dev *ADC3; +#endif + +/* + * Register map base pointers + */ + +/** ADC1 register map base pointer. */ +#define ADC1_BASE ((struct adc_reg_map*)0x40012400) +/** ADC2 register map base pointer. */ +#define ADC2_BASE ((struct adc_reg_map*)0x40012800) +#ifdef STM32_HIGH_DENSITY +/** ADC3 register map base pointer. */ +#define ADC3_BASE ((struct adc_reg_map*)0x40013C00) +#endif + +/* + * Register bit definitions + */ + +/* Control register 2 */ + +#define ADC_CR2_ADON_BIT 0 +#define ADC_CR2_CONT_BIT 1 +#define ADC_CR2_CAL_BIT 2 +#define ADC_CR2_RSTCAL_BIT 3 +#define ADC_CR2_DMA_BIT 8 +#define ADC_CR2_ALIGN_BIT 11 +#define ADC_CR2_JEXTTRIG_BIT 15 +#define ADC_CR2_EXTTRIG_BIT 20 +#define ADC_CR2_JSWSTART_BIT 21 +#define ADC_CR2_SWSTART_BIT 22 +#define ADC_CR2_TSEREFE_BIT 23 + +#define ADC_CR2_ADON (1U << ADC_CR2_ADON_BIT) +#define ADC_CR2_CONT (1U << ADC_CR2_CONT_BIT) +#define ADC_CR2_CAL (1U << ADC_CR2_CAL_BIT) +#define ADC_CR2_RSTCAL (1U << ADC_CR2_RSTCAL_BIT) +#define ADC_CR2_DMA (1U << ADC_CR2_DMA_BIT) +#define ADC_CR2_ALIGN (1U << ADC_CR2_ALIGN_BIT) +#define ADC_CR2_JEXTSEL 0x7000 +#define ADC_CR2_JEXTTRIG (1U << ADC_CR2_JEXTTRIG_BIT) +#define ADC_CR2_EXTSEL 0xE0000 +#define ADC_CR2_EXTTRIG (1U << ADC_CR2_EXTTRIG_BIT) +#define ADC_CR2_JSWSTART (1U << ADC_CR2_JSWSTART_BIT) +#define ADC_CR2_SWSTART (1U << ADC_CR2_SWSTART_BIT) +#define ADC_CR2_TSEREFE (1U << ADC_CR2_TSEREFE_BIT) + +/* + * Other types + */ + +/** + * @brief STM32F1 external event selectors for regular group + * conversion. + * + * Some external events are only available on ADCs 1 and 2, others + * only on ADC3, while others are available on all three ADCs. + * Additionally, some events are only available on high- and + * XL-density STM32F1 MCUs, as they use peripherals only available on + * those MCU densities. + * + * For ease of use, each event selector is given along with the ADCs + * it's available on, along with any other availability restrictions. + * + * @see adc_set_extsel() + */ +typedef enum adc_extsel_event { + /* TODO: Smarten this up a bit, as follows. + * + * The EXTSEL bits on F1 are a little brain-damaged in that the + * TIM8 TRGO event has different bits depending on whether you're + * using ADC1/2 or ADC3. We route around this by declaring two + * enumerators, ADC_EXT_EV_ADC12_TIM8_TRGO and + * ADC_EXT_EV_ADC3_TIM8_TRGO. + * + * The right thing to do is to provide a single + * ADC_EXT_EV_TIM8_TRGO enumerator and override adc_set_extsel on + * STM32F1 to handle this situation correctly. We can do that + * later, though, and change the per-ADC enumerator values to + * ADC_EXT_EV_TIM8_TRGO to preserve compatibility. */ + + /* ADC1 and ADC2 only: */ + ADC_EXT_EV_TIM1_CC1 = 0x00000, /**< ADC1, ADC2: Timer 1 CC1 event */ + ADC_EXT_EV_TIM1_CC2 = 0x20000, /**< ADC1, ADC2: Timer 1 CC2 event */ + ADC_EXT_EV_TIM2_CC2 = 0x60000, /**< ADC1, ADC2: Timer 2 CC2 event */ + ADC_EXT_EV_TIM3_TRGO = 0x80000, /**< ADC1, ADC2: Timer 3 TRGO event */ + ADC_EXT_EV_TIM4_CC4 = 0xA0000, /**< ADC1, ADC2: Timer 4 CC4 event */ + ADC_EXT_EV_EXTI11 = 0xC0000, /**< ADC1, ADC2: EXTI11 event */ + + /* Common: */ + ADC_EXT_EV_TIM1_CC3 = 0x40000, /**< ADC1, ADC2, ADC3: Timer 1 CC3 event */ + ADC_EXT_EV_SWSTART = 0xE0000, /**< ADC1, ADC2, ADC3: Software start */ + + /* HD only: */ + ADC_EXT_EV_TIM3_CC1 = 0x00000, /**< + * ADC3: Timer 3 CC1 event + * Availability: high- and XL-density. */ + ADC_EXT_EV_TIM2_CC3 = 0x20000, /**< + * ADC3: Timer 2 CC3 event + * Availability: high- and XL-density. */ + ADC_EXT_EV_TIM8_CC1 = 0x60000, /**< + * ADC3: Timer 8 CC1 event + * Availability: high- and XL-density. */ + ADC_EXT_EV_ADC3_TIM8_TRGO = 0x80000, /**< + * ADC3: Timer 8 TRGO event + * Availability: high- and XL-density. */ + ADC_EXT_EV_TIM5_CC1 = 0xA0000, /**< + * ADC3: Timer 5 CC1 event + * Availability: high- and XL-density. */ + ADC_EXT_EV_ADC12_TIM8_TRGO = 0xC0000, /**< + * ADC1, ADC2: Timer 8 TRGO event + * Availability: high- and XL-density. */ + ADC_EXT_EV_TIM5_CC3 = 0xC0000, /**< + * ADC3: Timer 5 CC3 event + * Availability: high- and XL-density. */ +} adc_extsel_event; + +/* We'll keep these old adc_extsel_event enumerators around for a + * while, for backwards compatibility: */ +/** Deprecated. Use ADC_EXT_EV_TIM1_CC1 instead. */ +#define ADC_ADC12_TIM1_CC1 ADC_EXT_EV_TIM1_CC1 +/** Deprecated. Use ADC_EXT_EV_TIM1_CC2 instead. */ +#define ADC_ADC12_TIM1_CC2 ADC_EXT_EV_TIM1_CC2 +/** Deprecated. Use ADC_EXT_EV_TIM1_CC3 instead. */ +#define ADC_ADC12_TIM1_CC3 ADC_EXT_EV_TIM1_CC3 +/** Deprecated. Use ADC_EXT_EV_TIM2_CC2 instead. */ +#define ADC_ADC12_TIM2_CC2 ADC_EXT_EV_TIM2_CC2 +/** Deprecated. Use ADC_EXT_EV_TIM3_TRGO instead. */ +#define ADC_ADC12_TIM3_TRGO ADC_EXT_EV_TIM3_TRGO +/** Deprecated. Use ADC_EXT_EV_TIM4_CC4 instead. */ +#define ADC_ADC12_TIM4_CC4 ADC_EXT_EV_TIM4_CC4 +/** Deprecated. Use ADC_EXT_EV_EXTI11 instead. */ +#define ADC_ADC12_EXTI11 ADC_EXT_EV_EXTI11 +/** Deprecated. Use ADC_EXT_EV_ADC12_TIM8_TRGO instead. */ +#define ADC_ADC12_TIM8_TRGO ADC_EXT_EV_ADC12_TIM8_TRGO +/** Deprecated. Use ADC_EXT_EV_SWSTART instead. */ +#define ADC_ADC12_SWSTART ADC_EXT_EV_SWSTART +/** Deprecated. Use ADC_EXT_EV_TIM1_CC1 instead. */ +#define ADC_ADC3_TIM3_CC1 ADC_EXT_EV_TIM1_CC1 +/** Deprecated. Use ADC_EXT_EV_TIM1_CC2 instead. */ +#define ADC_ADC3_TIM2_CC3 ADC_EXT_EV_TIM1_CC2 +/** Deprecated. Use ADC_EXT_EV_TIM1_CC3 instead. */ +#define ADC_ADC3_TIM1_CC3 ADC_EXT_EV_TIM1_CC3 +/** Deprecated. Use ADC_EXT_EV_TIM2_CC2 instead. */ +#define ADC_ADC3_TIM8_CC1 ADC_EXT_EV_TIM2_CC2 +/** Deprecated. Use ADC_EXT_EV_TIM3_TRGO instead. */ +#define ADC_ADC3_TIM8_TRGO ADC_EXT_EV_TIM3_TRGO +/** Deprecated. Use ADC_EXT_EV_TIM4_CC4 instead. */ +#define ADC_ADC3_TIM5_CC1 ADC_EXT_EV_TIM4_CC4 +/** Deprecated. Use ADC_EXT_EV_EXTI11 instead. */ +#define ADC_ADC3_TIM5_CC3 ADC_EXT_EV_EXTI11 +/** Deprecated. Use ADC_EXT_EV_TIM8_TRGO instead. */ +#define ADC_ADC3_SWSTART ADC_EXT_EV_TIM8_TRGO +/** Deprecated. Use ADC_EXT_EV_SWSTART instead. */ +#define ADC_SWSTART ADC_EXT_EV_SWSTART + +/** + * @brief STM32F1 sample times, in ADC clock cycles. + * + * These control the amount of time spent sampling the input voltage. + * + * IMPORTANT: maximum external impedance must be below 0.4kOhms for + * 1.5 cycle sampling time. At 55.5 cycles/sample, the external input + * impedance must be at most 50kOhms. See your device's datasheet for + * more information. + */ +typedef enum adc_smp_rate { + ADC_SMPR_1_5, /**< 1.5 ADC cycles */ + ADC_SMPR_7_5, /**< 7.5 ADC cycles */ + ADC_SMPR_13_5, /**< 13.5 ADC cycles */ + ADC_SMPR_28_5, /**< 28.5 ADC cycles */ + ADC_SMPR_41_5, /**< 41.5 ADC cycles */ + ADC_SMPR_55_5, /**< 55.5 ADC cycles */ + ADC_SMPR_71_5, /**< 71.5 ADC cycles */ + ADC_SMPR_239_5, /**< 239.5 ADC cycles */ +} adc_smp_rate; + +/** + * @brief STM32F1 ADC prescalers, as divisors of PCLK2. + */ +typedef enum adc_prescaler { + ADC_PRE_PCLK2_DIV_2 = RCC_ADCPRE_PCLK_DIV_2, /** PCLK2 divided by 2 */ + ADC_PRE_PCLK2_DIV_4 = RCC_ADCPRE_PCLK_DIV_4, /** PCLK2 divided by 4 */ + ADC_PRE_PCLK2_DIV_6 = RCC_ADCPRE_PCLK_DIV_6, /** PCLK2 divided by 6 */ + ADC_PRE_PCLK2_DIV_8 = RCC_ADCPRE_PCLK_DIV_8, /** PCLK2 divided by 8 */ +} adc_prescaler; + +/* + * Routines + */ + +void adc_calibrate(const adc_dev *dev); + +/** + * @brief Set external trigger conversion mode event for regular channels + * + * Availability: STM32F1. + * + * @param dev ADC device + * @param enable If 1, conversion on external events is enabled; if 0, + * disabled. + */ +static inline void adc_set_exttrig(const adc_dev *dev, uint8 enable) { + *bb_perip(&dev->regs->CR2, ADC_CR2_EXTTRIG_BIT) = !!enable; +} + +#endif diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk index bdff00e..c0d6344 100644 --- a/libmaple/stm32f1/rules.mk +++ b/libmaple/stm32f1/rules.mk @@ -11,7 +11,8 @@ CFLAGS_$(d) = -I$(d) $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -We sSRCS_$(d) := isrs_performance.S sSRCS_$(d) += vector_table_performance.S -cSRCS_$(d) := bkp.c +cSRCS_$(d) := adc.c +cSRCS_$(d) += bkp.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c cSRCS_$(d) += rcc.c diff --git a/libmaple/stm32f2/adc.c b/libmaple/stm32f2/adc.c new file mode 100644 index 0000000..fbe1618 --- /dev/null +++ b/libmaple/stm32f2/adc.c @@ -0,0 +1,84 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/include/series/adc.c + * @brief STM32F2 ADC header. + */ + +#include +#include + +/* + * Devices + */ + +static adc_dev adc1 = { + .regs = ADC1_BASE, + .clk_id = RCC_ADC1, +}; +/** ADC1 device. */ +const adc_dev *ADC1 = &adc1; + +static adc_dev adc2 = { + .regs = ADC2_BASE, + .clk_id = RCC_ADC2, +}; +/** ADC2 device. */ +const adc_dev *ADC2 = &adc2; + +adc_dev adc3 = { + .regs = ADC3_BASE, + .clk_id = RCC_ADC3, +}; +/** ADC3 device. */ +const adc_dev *ADC3 = &adc3; + +/* + * Common routines + */ + +void adc_set_prescaler(adc_prescaler pre) { + uint32 ccr = ADC_COMMON_BASE->CCR; + ccr &= ~ADC_CCR_ADCPRE; + ccr |= (uint32)pre; + ADC_COMMON_BASE->CCR = ccr; +} + +void adc_foreach(void (*fn)(const adc_dev*)) { + fn(ADC1); + fn(ADC2); + fn(ADC3); +} + +void adc_gpio_cfg(gpio_dev *gdev, uint8 bit) { + gpio_set_modef(gdev, bit, GPIO_MODE_ANALOG, GPIO_MODEF_PUPD_NONE); +} + +void adc_enable_single_swstart(const adc_dev *dev) { + adc_init(dev); + adc_enable(dev); +} diff --git a/libmaple/stm32f2/include/series/adc.h b/libmaple/stm32f2/include/series/adc.h new file mode 100644 index 0000000..4f0cd6b --- /dev/null +++ b/libmaple/stm32f2/include/series/adc.h @@ -0,0 +1,331 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file stm32f2/include/series/adc.h + * @author Marti Bolivar , + * @brief STM32F2 ADC header. + */ + +#ifndef _LIBMAPLE_STM32F2_ADC_H_ +#define _LIBMAPLE_STM32F2_ADC_H_ + +#include + +/* + * Devices + */ + +extern const struct adc_dev *ADC1; +extern const struct adc_dev *ADC2; +extern const struct adc_dev *ADC3; + +/* + * Common register map + */ + +/** ADC common register map type */ +typedef struct adc_common_reg_map { + __io uint32 CSR; /**< Common status register */ + __io uint32 CCR; /**< Common control register */ + __io uint32 CDR; /**< + * @brief Common regular data register + * for dual and triple modes */ +} adc_common_reg_map; + +/* + * Register map base pointers + */ + +/** ADC1 register map base pointer. */ +#define ADC1_BASE ((struct adc_reg_map*)0x40012000) +/** ADC2 register map base pointer. */ +#define ADC2_BASE ((struct adc_reg_map*)0x40012100) +/** ADC3 register map base pointer. */ +#define ADC3_BASE ((struct adc_reg_map*)0x40012200) +/** ADC common register map base pointer. */ +#define ADC_COMMON_BASE ((struct adc_common_reg_map*)0x40012300) + +/* + * Register bit definitions + */ + +/* Status register */ + +/** Overrun bit. */ +#define ADC_SR_OVR_BIT 5 +/** Overrun. */ +#define ADC_SR_OVR (1U << ADC_SR_OVR_BIT) + +/* Control register 1 */ + +/** Overrun interrupt enable bit. */ +#define ADC_CR1_OVRIE_BIT 26 + +/** Overrun interrupt error enable. */ +#define ADC_CR1_OVRIE (1U << ADC_CR1_OVRIE_BIT) +/** Conversion resolution. */ +#define ADC_CR1_RES (0x3U << 24) +/** Conversion resolution: 12 bit (at least 15 ADCCLK cycles). */ +#define ADC_CR1_RES_12BIT (0x0U << 24) +/** Conversion resolution: 10 bit (at least 13 ADCCLK cycles). */ +#define ADC_CR1_RES_10BIT (0x1U << 24) +/** Conversion resolution: 8 bit (at least 11 ADCCLK cycles). */ +#define ADC_CR1_RES_8BIT (0x2U << 24) +/** Conversion resolution: 6 bit (at least 9 ADCCLK cycles). */ +#define ADC_CR1_RES_6BIT (0x3U << 24) + +/* Control register 2 */ + +#define ADC_CR2_SWSTART_BIT 30 +#define ADC_CR2_JSWSTART_BIT 22 +#define ADC_CR2_ALIGN_BIT 11 +#define ADC_CR2_EOCS_BIT 10 +#define ADC_CR2_DDS_BIT 9 +#define ADC_CR2_DMA_BIT 8 +#define ADC_CR2_CONT_BIT 1 +#define ADC_CR2_ADON_BIT 0 + +#define ADC_CR2_SWSTART (1U << ADC_CR2_SWSTART_BIT) +#define ADC_CR2_EXTEN (0x3 << 28) +#define ADC_CR2_EXTEN_DISABLED (0x0 << 28) +#define ADC_CR2_EXTEN_RISE (0x1 << 28) +#define ADC_CR2_EXTEN_FALL (0x2 << 28) +#define ADC_CR2_EXTEN_RISE_FALL (0x3 << 28) +#define ADC_CR2_EXTSEL (0xF << 24) +#define ADC_CR2_EXTSEL_TIM1_CC1 (0x0 << 24) +#define ADC_CR2_EXTSEL_TIM1_CC2 (0x1 << 24) +#define ADC_CR2_EXTSEL_TIM1_CC3 (0x2 << 24) +#define ADC_CR2_EXTSEL_TIM2_CC2 (0x3 << 24) +#define ADC_CR2_EXTSEL_TIM2_CC3 (0x4 << 24) +#define ADC_CR2_EXTSEL_TIM2_CC4 (0x5 << 24) +#define ADC_CR2_EXTSEL_TIM1_TRGO (0x6 << 24) +#define ADC_CR2_EXTSEL_TIM3_CC1 (0x7 << 24) +#define ADC_CR2_EXTSEL_TIM3_TRGO (0x8 << 24) +#define ADC_CR2_EXTSEL_TIM4_CC4 (0x9 << 24) +#define ADC_CR2_EXTSEL_TIM5_CC1 (0xA << 24) +#define ADC_CR2_EXTSEL_TIM5_CC2 (0xB << 24) +#define ADC_CR2_EXTSEL_TIM5_CC3 (0xC << 24) +#define ADC_CR2_EXTSEL_TIM8_CC1 (0xD << 24) +#define ADC_CR2_EXTSEL_TIM8_TRGO (0xE << 24) +#define ADC_CR2_EXTSEL_TIM1_EXTI11 (0xF << 24) +#define ADC_CR2_JSWSTART (1U << ADC_CR2_JSWSTART_BIT) +#define ADC_CR2_JEXTEN (0x3 << 20) +#define ADC_CR2_JEXTEN_DISABLED (0x0 << 20) +#define ADC_CR2_JEXTEN_RISE (0x1 << 20) +#define ADC_CR2_JEXTEN_FALL (0x2 << 20) +#define ADC_CR2_JEXTEN_RISE_FALL (0x3 << 20) +#define ADC_CR2_JEXTSEL (0xF << 16) +#define ADC_CR2_JEXTSEL_TIM1_CC4 (0x0 << 16) +#define ADC_CR2_JEXTSEL_TIM1_TRGO (0x1 << 16) +#define ADC_CR2_JEXTSEL_TIM2_CC1 (0x2 << 16) +#define ADC_CR2_JEXTSEL_TIM2_TRGO (0x3 << 16) +#define ADC_CR2_JEXTSEL_TIM3_CC2 (0x4 << 16) +#define ADC_CR2_JEXTSEL_TIM3_CC4 (0x5 << 16) +#define ADC_CR2_JEXTSEL_TIM4_CC1 (0x6 << 16) +#define ADC_CR2_JEXTSEL_TIM4_CC2 (0x7 << 16) +#define ADC_CR2_JEXTSEL_TIM4_CC3 (0x8 << 16) +#define ADC_CR2_JEXTSEL_TIM4_TRGO (0x9 << 16) +#define ADC_CR2_JEXTSEL_TIM5_CC4 (0xA << 16) +#define ADC_CR2_JEXTSEL_TIM5_TRGO (0xB << 16) +#define ADC_CR2_JEXTSEL_TIM8_CC2 (0xC << 16) +#define ADC_CR2_JEXTSEL_TIM8_CC3 (0xD << 16) +#define ADC_CR2_JEXTSEL_TIM8_CC4 (0xE << 16) +#define ADC_CR2_JEXTSEL_TIM1_EXTI15 (0xF << 16) +#define ADC_CR2_ALIGN (1U << ADC_CR2_ALIGN_BIT) +#define ADC_CR2_ALIGN_RIGHT (0U << ADC_CR2_ALIGN_BIT) +#define ADC_CR2_ALIGN_LEFT (1U << ADC_CR2_ALIGN_BIT) +#define ADC_CR2_EOCS (1U << ADC_CR2_EOCS_BIT) +#define ADC_CR2_EOCS_SEQUENCE (0U << ADC_CR2_EOCS_BIT) +#define ADC_CR2_EOCS_CONVERSION (1U << ADC_CR2_EOCS_BIT) +#define ADC_CR2_DDS (1U << ADC_CR2_DDS_BIT) +#define ADC_CR2_DMA (1U << ADC_CR2_DMA_BIT) +#define ADC_CR2_CONT (1U << ADC_CR2_CONT_BIT) +#define ADC_CR2_ADON (1U << ADC_CR2_ADON_BIT) + +/* Common status register */ + +#define ADC_CSR_OVR3_BIT 21 +#define ADC_CSR_STRT3_BIT 20 +#define ADC_CSR_JSTRT3_BIT 19 +#define ADC_CSR_JEOC3_BIT 18 +#define ADC_CSR_EOC3_BIT 17 +#define ADC_CSR_AWD3_BIT 16 +#define ADC_CSR_OVR2_BIT 13 +#define ADC_CSR_STRT2_BIT 12 +#define ADC_CSR_JSTRT2_BIT 11 +#define ADC_CSR_JEOC2_BIT 10 +#define ADC_CSR_EOC2_BIT 9 +#define ADC_CSR_AWD2_BIT 8 +#define ADC_CSR_OVR1_BIT 5 +#define ADC_CSR_STRT1_BIT 4 +#define ADC_CSR_JSTRT1_BIT 3 +#define ADC_CSR_JEOC1_BIT 2 +#define ADC_CSR_EOC1_BIT 1 +#define ADC_CSR_AWD1_BIT 0 + +#define ADC_CSR_OVR3 (1U << ADC_CSR_OVR3_BIT) +#define ADC_CSR_STRT3 (1U << ADC_CSR_STRT3_BIT) +#define ADC_CSR_JSTRT3 (1U << ADC_CSR_JSTRT3_BIT) +#define ADC_CSR_JEOC3 (1U << ADC_CSR_JEOC3_BIT) +#define ADC_CSR_EOC3 (1U << ADC_CSR_EOC3_BIT) +#define ADC_CSR_AWD3 (1U << ADC_CSR_AWD3_BIT) +#define ADC_CSR_OVR2 (1U << ADC_CSR_OVR2_BIT) +#define ADC_CSR_STRT2 (1U << ADC_CSR_STRT2_BIT) +#define ADC_CSR_JSTRT2 (1U << ADC_CSR_JSTRT2_BIT) +#define ADC_CSR_JEOC2 (1U << ADC_CSR_JEOC2_BIT) +#define ADC_CSR_EOC2 (1U << ADC_CSR_EOC2_BIT) +#define ADC_CSR_AWD2 (1U << ADC_CSR_AWD2_BIT) +#define ADC_CSR_OVR1 (1U << ADC_CSR_OVR1_BIT) +#define ADC_CSR_STRT1 (1U << ADC_CSR_STRT1_BIT) +#define ADC_CSR_JSTRT1 (1U << ADC_CSR_JSTRT1_BIT) +#define ADC_CSR_JEOC1 (1U << ADC_CSR_JEOC1_BIT) +#define ADC_CSR_EOC1 (1U << ADC_CSR_EOC1_BIT) +#define ADC_CSR_AWD1 (1U << ADC_CSR_AWD1_BIT) + +/* Common control register */ + +#define ADC_CCR_TSVREFE_BIT 23 +#define ADC_CCR_VBATE_BIT 22 +#define ADC_CCR_DDS_BIT 13 + +#define ADC_CCR_TSVREFE (1U << ADC_CCR_TSVREFE_BIT) +#define ADC_CCR_VBATE (1U << ADC_CCR_VBATE_BIT) +#define ADC_CCR_ADCPRE (0x3 << 16) +#define ADC_CCR_ADCPRE_PCLK2_DIV_2 (0x0 << 16) +#define ADC_CCR_ADCPRE_PCLK2_DIV_4 (0x1 << 16) +#define ADC_CCR_ADCPRE_PCLK2_DIV_6 (0x2 << 16) +#define ADC_CCR_ADCPRE_PCLK2_DIV_8 (0x3 << 16) +#define ADC_CCR_DMA (0x3 << 14) +#define ADC_CCR_DMA_DIS (0x0 << 14) +#define ADC_CCR_DMA_MODE_1 (0x1 << 14) +#define ADC_CCR_DMA_MODE_2 (0x2 << 14) +#define ADC_CCR_DMA_MODE_3 (0x3 << 14) +#define ADC_CCR_DDS (1U << ADC_CCR_DDS_BIT) +#define ADC_CCR_DELAY (0xF << 8) +#define ADC_CCR_DELAY_5 (0x0 << 8) +#define ADC_CCR_DELAY_6 (0x1 << 8) +#define ADC_CCR_DELAY_7 (0x2 << 8) +#define ADC_CCR_DELAY_8 (0x3 << 8) +#define ADC_CCR_DELAY_9 (0x4 << 8) +#define ADC_CCR_DELAY_10 (0x5 << 8) +#define ADC_CCR_DELAY_11 (0x6 << 8) +#define ADC_CCR_DELAY_12 (0x7 << 8) +#define ADC_CCR_DELAY_13 (0x8 << 8) +#define ADC_CCR_DELAY_14 (0x9 << 8) +#define ADC_CCR_DELAY_15 (0xA << 8) +#define ADC_CCR_DELAY_16 (0xB << 8) +#define ADC_CCR_DELAY_17 (0xC << 8) +#define ADC_CCR_DELAY_18 (0xD << 8) +#define ADC_CCR_DELAY_19 (0xE << 8) +#define ADC_CCR_DELAY_20 (0xF << 8) +/** Multi ADC mode selection. */ +#define ADC_CCR_MULTI 0x1F +/** All ADCs independent. */ +#define ADC_CCR_MULTI_INDEPENDENT 0x0 +/** Dual mode: combined regular simultaneous/injected simultaneous. */ +#define ADC_CCR_MULTI_DUAL_REG_SIM_INJ_SIM 0x1 +/** Dual mode: combined regular simultaneous/alternate trigger. */ +#define ADC_CCR_MULTI_DUAL_REG_SIM_ALT_TRIG 0x2 +/** Dual mode: injected simultaneous mode only. */ +#define ADC_CCR_MULTI_DUAL_INJ_SIM 0x5 +/** Dual mode: regular simultaneous mode only. */ +#define ADC_CCR_MULTI_DUAL_REG_SIM 0x6 +/** Dual mode: interleaved mode only. */ +#define ADC_CCR_MULTI_DUAL_INTER 0x7 +/** Dual mode: alternate trigger mode only. */ +#define ADC_CCR_MULTI_DUAL_ALT_TRIG 0x9 +/** Triple mode: combined regular simultaneous/injected simultaneous. */ +#define ADC_CCR_MULTI_TRIPLE_REG_SIM_INJ_SIM 0x10 +/** Triple mode: combined regular simultaneous/alternate trigger. */ +#define ADC_CCR_MULTI_TRIPLE_REG_SIM_ALT_TRIG 0x11 +/** Triple mode: injected simultaneous mode only. */ +#define ADC_CCR_MULTI_TRIPLE_INJ_SIM 0x12 +/** Triple mode: regular simultaneous mode only. */ +#define ADC_CCR_MULTI_TRIPLE_REG_SIM 0x15 +/** Triple mode: interleaved mode only. */ +#define ADC_CCR_MULTI_TRIPLE_INTER 0x17 +/** Triple mode: alternate trigger mode only. */ +#define ADC_CCR_MULTI_TRIPLE_ALT_TRIG 0x19 + +/* Common regular data register for dual and triple modes */ + +#define ADC_CDR_DATA2 0xFFFF0000 +#define ADC_CDR_DATA1 0xFFFF + +/* + * Other types + */ + +/** + * @brief STM32F2 external event selectors for regular group + * conversion. + * @see adc_set_extsel() + */ +typedef enum adc_extsel_event { + ADC_EXT_EV_TIM1_CC1 = ADC_CR2_EXTSEL_TIM1_CC1, + ADC_EXT_EV_TIM1_CC2 = ADC_CR2_EXTSEL_TIM1_CC2, + ADC_EXT_EV_TIM1_CC3 = ADC_CR2_EXTSEL_TIM1_CC3, + ADC_EXT_EV_TIM2_CC2 = ADC_CR2_EXTSEL_TIM2_CC2, + ADC_EXT_EV_TIM2_CC3 = ADC_CR2_EXTSEL_TIM2_CC3, + ADC_EXT_EV_TIM2_CC4 = ADC_CR2_EXTSEL_TIM2_CC4, + ADC_EXT_EV_TIM1_TRGO = ADC_CR2_EXTSEL_TIM1_TRGO, + ADC_EXT_EV_TIM3_CC1 = ADC_CR2_EXTSEL_TIM3_CC1, + ADC_EXT_EV_TIM3_TRGO = ADC_CR2_EXTSEL_TIM3_TRGO, + ADC_EXT_EV_TIM4_CC4 = ADC_CR2_EXTSEL_TIM4_CC4, + ADC_EXT_EV_TIM5_CC1 = ADC_CR2_EXTSEL_TIM5_CC1, + ADC_EXT_EV_TIM5_CC2 = ADC_CR2_EXTSEL_TIM5_CC2, + ADC_EXT_EV_TIM5_CC3 = ADC_CR2_EXTSEL_TIM5_CC3, + ADC_EXT_EV_TIM8_CC1 = ADC_CR2_EXTSEL_TIM8_CC1, + ADC_EXT_EV_TIM8_TRGO = ADC_CR2_EXTSEL_TIM8_TRGO, + ADC_EXT_EV_TIM1_EXTI11 = ADC_CR2_EXTSEL_TIM1_EXTI11, +} adc_extsel_event; + +/** + * @brief STM32F2 sample times, in ADC clock cycles. + */ +typedef enum adc_smp_rate { + ADC_SMPR_3, /**< 3 ADC cycles */ + ADC_SMPR_15, /**< 15 ADC cycles */ + ADC_SMPR_28, /**< 28 ADC cycles */ + ADC_SMPR_56, /**< 56 ADC cycles */ + ADC_SMPR_84, /**< 84 ADC cycles */ + ADC_SMPR_112, /**< 112 ADC cycles */ + ADC_SMPR_144, /**< 144 ADC cycles */ + ADC_SMPR_480, /**< 480 ADC cycles */ +} adc_smp_rate; + +/** + * @brief STM32F2 ADC prescalers, as divisors of PCLK2. + */ +typedef enum adc_prescaler { + ADC_PRE_PCLK2_DIV_2 = ADC_CCR_ADCPRE_PCLK2_DIV_2, /** PCLK2 divided by 2 */ + ADC_PRE_PCLK2_DIV_4 = ADC_CCR_ADCPRE_PCLK2_DIV_4, /** PCLK2 divided by 4 */ + ADC_PRE_PCLK2_DIV_6 = ADC_CCR_ADCPRE_PCLK2_DIV_6, /** PCLK2 divided by 6 */ + ADC_PRE_PCLK2_DIV_8 = ADC_CCR_ADCPRE_PCLK2_DIV_8, /** PCLK2 divided by 8 */ +} adc_prescaler; + +#endif diff --git a/libmaple/stm32f2/rules.mk b/libmaple/stm32f2/rules.mk index a46f8d1..5951b94 100644 --- a/libmaple/stm32f2/rules.mk +++ b/libmaple/stm32f2/rules.mk @@ -11,6 +11,7 @@ CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) $(LIBMAPLE_PRIVATE_INCLUDES) -Wall -We sSRCS_$(d) := isrs.S sSRCS_$(d) += vector_table.S +cSRCS_$(d) := adc.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c cSRCS_$(d) += rcc.c diff --git a/wirish/boards.cpp b/wirish/boards.cpp index 04b359f..54807d3 100644 --- a/wirish/boards.cpp +++ b/wirish/boards.cpp @@ -54,6 +54,7 @@ static void setup_flash(void); static void setup_clocks(void); static void setup_nvic(void); +static void setup_adcs(void); /* * Exported functions @@ -65,7 +66,7 @@ void init(void) { setup_nvic(); systick_init(SYSTICK_RELOAD_VAL); wirish::priv::board_setup_gpio(); - wirish::priv::board_setup_adc(); + setup_adcs(); wirish::priv::board_setup_timers(); wirish::priv::board_setup_usb(); boardInit(); @@ -124,7 +125,7 @@ static void setup_clocks(void) { // Configure AHBx, APBx, etc. prescalers and the main PLL. wirish::priv::board_setup_clock_prescalers(); - rcc_configure_pll(&wirish::priv::board_pll_cfg); + rcc_configure_pll(&wirish::priv::w_board_pll_cfg); // Enable the PLL, and wait until it's ready. rcc_turn_on_clk(RCC_CLK_PLL); @@ -146,3 +147,13 @@ static void setup_nvic(void) { #error "You must select a base address for the vector table." #endif } + +static void adc_default_config(const adc_dev *dev) { + adc_enable_single_swstart(dev); + adc_set_sample_rate(dev, wirish::priv::w_adc_smp); +} + +static void setup_adcs(void) { + adc_set_prescaler(wirish::priv::w_adc_pre); + adc_foreach(adc_default_config); +} diff --git a/wirish/boards_private.h b/wirish/boards_private.h index a4101c9..e32f298 100644 --- a/wirish/boards_private.h +++ b/wirish/boards_private.h @@ -28,11 +28,18 @@ * @file wirish/boards_private.h * @author Marti Bolivar * @brief Private board support header. + * + * This file declares chip-specific variables and functions which + * determine how init() behaves. It is not part of the public Wirish + * API, and can change without notice. */ #ifndef _WIRISH_BOARDS_PRIVATE_H_ #define _WIRISH_BOARDS_PRIVATE_H_ +#include +#include + namespace wirish { namespace priv { @@ -40,7 +47,9 @@ namespace wirish { * Chip-specific initialization data */ - extern rcc_pll_cfg board_pll_cfg; + extern rcc_pll_cfg w_board_pll_cfg; + extern adc_prescaler w_adc_pre; + extern adc_smp_rate w_adc_smp; /* * Chip-specific initialization routines and helper functions. @@ -49,7 +58,6 @@ namespace wirish { void board_reset_pll(void); void board_setup_clock_prescalers(void); void board_setup_gpio(void); - void board_setup_adc(void); void board_setup_timers(void); void board_setup_usb(void); diff --git a/wirish/stm32f1/boards_setup.cpp b/wirish/stm32f1/boards_setup.cpp index 4ee292a..8e16009 100644 --- a/wirish/stm32f1/boards_setup.cpp +++ b/wirish/stm32f1/boards_setup.cpp @@ -28,11 +28,15 @@ * @file wirish/stm32f1/boards_setup.cpp * @author Marti Bolivar * @brief STM32F1 chip setup. + * + * This file controls how init() behaves on the STM32F1. Be very + * careful when changing anything here. Many of these values depend + * upon each other. */ -#include +#include "boards_private.h" + #include -#include #include #include @@ -45,12 +49,11 @@ namespace wirish { namespace priv { static stm32f1_rcc_pll_data pll_data = {RCC_PLLMUL_9}; - rcc_pll_cfg board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; + rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; + adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6; + adc_smp_rate w_adc_smp = ADC_SMPR_55_5; -#if 0 - static void config_adc(const adc_dev* dev); static void config_timer(timer_dev*); -#endif void board_reset_pll(void) { // TODO @@ -69,17 +72,8 @@ namespace wirish { afio_init(); } - void board_setup_adc(void) { -#if 0 - rcc_set_prescaler(RCC_PRESCALER_ADC, RCC_ADCPRE_PCLK_DIV_6); - adc_foreach(config_adc); -#endif - } - void board_setup_timers(void) { -#if 0 timer_foreach(config_timer); -#endif } void board_setup_usb(void) { @@ -92,19 +86,8 @@ namespace wirish { * Auxiliary routines */ -#if 0 - static void config_adc(const adc_dev *dev) { - adc_init(dev); - - adc_set_extsel(dev, ADC_SWSTART); - adc_set_exttrig(dev, true); - - adc_enable(dev); - adc_calibrate(dev); - adc_set_sample_rate(dev, ADC_SMPR_55_5); - } - static void config_timer(timer_dev *dev) { +#if 0 timer_adv_reg_map *regs = (dev->regs).adv; const uint16 full_overflow = 0xFFFF; const uint16 half_duty = 0x8FFF; @@ -135,7 +118,7 @@ namespace wirish { } timer_resume(dev); - } #endif + } } } diff --git a/wirish/stm32f2/boards_setup.cpp b/wirish/stm32f2/boards_setup.cpp index b3c690c..e1bf1fd 100644 --- a/wirish/stm32f2/boards_setup.cpp +++ b/wirish/stm32f2/boards_setup.cpp @@ -28,11 +28,18 @@ * @file wirish/stm32f2/boards_setup.cpp * @author Marti Bolivar * @brief STM32F2 chip setup. + * + * This file controls how init() behaves on the STM32F2. Be very + * careful when changing anything here. Many of these values depend + * upon each other. */ -#include +#include "boards_private.h" + #include +#include +// PLL configuration for 25 MHz external oscillator --> 120 MHz SYSCLK. #define PLL_Q 5 #define PLL_P 2 #define PLL_N 240 @@ -41,7 +48,18 @@ static stm32f2_rcc_pll_data pll_data = {PLL_Q, PLL_P, PLL_N, PLL_M}; namespace wirish { namespace priv { - rcc_pll_cfg board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; + // PLL clocked off of HSE, with above configuration data. + rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; + // As f_APB2 = 60 MHz (see board_setup_clock_prescalers), + // we need f_ADC = f_PCLK2 / 2 to get the (maximum) + // f_ADC = 30 MHz. + adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_2; + // With clocks as specified here (i.e. f_ADC = 30 MHz), this + // ADC sample rate allows for error less than 1/4 LSB with a + // 50 KOhm input impedance, assuming an internal sample and + // hold capacitance C_ADC at most 8.8 pF. See Equation 1 and + // Table 61 in the F2 datasheet for more details. + adc_smp_rate w_adc_smp = ADC_SMPR_144; void board_reset_pll(void) { // Set PLLCFGR to its reset value. @@ -49,8 +67,13 @@ namespace wirish { } void board_setup_clock_prescalers(void) { + // With f_SYSCLK = 120 MHz (as determined by board_pll_cfg), + // + // f_AHB = f_SYSCLK / 1 = 120 MHz rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1); + // f_APB1 = f_AHB / 4 = 30 MHz rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_4); + // f_APB2 = f_AHB / 2 = 60 MHz rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_2); } @@ -58,10 +81,6 @@ namespace wirish { gpio_init_all(); } - void board_setup_adc(void) { - // TODO - } - void board_setup_timers(void) { // TODO } @@ -72,4 +91,3 @@ namespace wirish { } } - -- cgit v1.2.3 From 014f9a0545556f2e0d4fb3faba5607e59e1e97ad Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 31 May 2012 17:17:06 -0400 Subject: examples/blinky.cpp works on F2. Only OUTPUT mode is tested; any other modes might work, but no guarantees. Bring back: - wirish/wirish_digital.cpp - wirish/cxxabi-compat.cpp - wirish/wirish_time.cpp Add new: - wirish/stm32f1/wirish_digital.cpp - wirish/stm32f2/wirish_digital.cpp Move pinMode() from wirish/wirish_digital.cpp into the file by the same basename in wirish/stm32f1. This implementation is tied to F1. Add an F2 implementation in wirish/stm32f2/wirish_digital.cpp. Signed-off-by: Marti Bolivar --- wirish/rules.mk | 14 ++-- wirish/stm32f1/wirish_digital.cpp | 89 ++++++++++++++++++++++++++ wirish/stm32f2/wirish_digital.cpp | 130 ++++++++++++++++++++++++++++++++++++++ wirish/wirish_digital.cpp | 54 +--------------- 4 files changed, 227 insertions(+), 60 deletions(-) create mode 100644 wirish/stm32f1/wirish_digital.cpp create mode 100644 wirish/stm32f2/wirish_digital.cpp (limited to 'wirish/stm32f2') diff --git a/wirish/rules.mk b/wirish/rules.mk index afd78e2..5e00a5f 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -21,6 +21,12 @@ CFLAGS_$(d) := $(LIBMAPLE_INCLUDES) $(WIRISH_INCLUDES) -I$(d) sSRCS_$(d) := start.S cSRCS_$(d) := start_c.c cppSRCS_$(d) := boards.cpp +cppSRCS_$(d) += cxxabi-compat.cpp +cppSRCS_$(d) += wirish_digital.cpp +cppSRCS_$(d) += wirish_time.cpp +cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp +cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp +cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp # TODO: test these on F2 and put them back in: # cppSRCS_$(d) := wirish_math.cpp \ # Print.cpp \ @@ -28,16 +34,10 @@ cppSRCS_$(d) := boards.cpp # HardwareSPI.cpp \ # HardwareTimer.cpp \ # usb_serial.cpp \ -# cxxabi-compat.cpp \ # wirish_shift.cpp \ # wirish_analog.cpp \ -# wirish_time.cpp \ # pwm.cpp \ -# ext_interrupts.cpp \ -# wirish_digital.cpp -# TODO: Put this back in once we've got the necessary libmaple support back. -cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp -cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp +# ext_interrupts.cpp sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) diff --git a/wirish/stm32f1/wirish_digital.cpp b/wirish/stm32f1/wirish_digital.cpp new file mode 100644 index 0000000..8371b0e --- /dev/null +++ b/wirish/stm32f1/wirish_digital.cpp @@ -0,0 +1,89 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/* + * STM32F1 implementations for basic GPIO functionality. + */ + +#include + +#include +#include + +#include + +void pinMode(uint8 pin, WiringPinMode mode) { + gpio_pin_mode outputMode; + bool pwm = false; + + if (pin >= BOARD_NR_GPIO_PINS) { + return; + } + + switch(mode) { + case OUTPUT: + outputMode = GPIO_OUTPUT_PP; + break; + case OUTPUT_OPEN_DRAIN: + outputMode = GPIO_OUTPUT_OD; + break; + case INPUT: + case INPUT_FLOATING: + outputMode = GPIO_INPUT_FLOATING; + break; + case INPUT_ANALOG: + outputMode = GPIO_INPUT_ANALOG; + break; + case INPUT_PULLUP: + outputMode = GPIO_INPUT_PU; + break; + case INPUT_PULLDOWN: + outputMode = GPIO_INPUT_PD; + break; + case PWM: + outputMode = GPIO_AF_OUTPUT_PP; + pwm = true; + break; + case PWM_OPEN_DRAIN: + outputMode = GPIO_AF_OUTPUT_OD; + pwm = true; + break; + default: + ASSERT(0); + return; + } + + gpio_set_mode(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, outputMode); + + if (PIN_MAP[pin].timer_device != NULL) { + /* Enable/disable timer channels if we're switching into or + * out of PWM. */ + timer_set_mode(PIN_MAP[pin].timer_device, + PIN_MAP[pin].timer_channel, + pwm ? TIMER_PWM : TIMER_DISABLED); + } +} diff --git a/wirish/stm32f2/wirish_digital.cpp b/wirish/stm32f2/wirish_digital.cpp new file mode 100644 index 0000000..a67111d --- /dev/null +++ b/wirish/stm32f2/wirish_digital.cpp @@ -0,0 +1,130 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/* + * STM32F2 implementations for basic GPIO functionality. + */ + +#include + +#include +#include + +#include + +void pinMode(uint8 pin, WiringPinMode w_mode) { + if (pin >= BOARD_NR_GPIO_PINS) { + return; + } + + gpio_pin_mode mode; + // People always do the silly pin-toggle speed benchmark, so let's + // accomodate them: + unsigned flags = GPIO_MODEF_SPEED_HIGH; + bool pwm = false; + switch(w_mode) { + case OUTPUT: + mode = GPIO_MODE_OUTPUT; + break; + case OUTPUT_OPEN_DRAIN: + mode = GPIO_MODE_OUTPUT; + flags |= GPIO_MODEF_TYPE_OD; + break; + case INPUT: + case INPUT_FLOATING: + mode = GPIO_MODE_INPUT; + break; + case INPUT_ANALOG: + mode = GPIO_MODE_ANALOG; + break; + case INPUT_PULLUP: + mode = GPIO_MODE_INPUT; + flags |= GPIO_MODEF_PUPD_PU; + break; + case INPUT_PULLDOWN: + mode = GPIO_MODE_INPUT; + flags |= GPIO_MODEF_PUPD_PD; + break; + case PWM: + mode = GPIO_MODE_AF; + pwm = true; + break; + case PWM_OPEN_DRAIN: + mode = GPIO_MODE_AF; + flags |= GPIO_MODEF_TYPE_OD; + pwm = true; + break; + default: + ASSERT(0); // Can't happen + return; + } + + const stm32_pin_info *info = &PIN_MAP[pin]; + + if (pwm) { + /* If enabling PWM, tell the timer to do PWM, and tell the pin + * to listen to the right timer. */ + ASSERT(info->timer_device != NULL); + if (info->timer_device == NULL) { + return; + } + gpio_af timer_af; + /* TODO make this code a convenience + * routine for series that support GPIO alternate + * functions. */ + switch(info->timer_device->clk_id) { + case RCC_TIMER1: // fall-through + case RCC_TIMER2: + timer_af = GPIO_AF_TIM_1_2; + break; + case RCC_TIMER3: // fall-through + case RCC_TIMER4: // ... + case RCC_TIMER5: + timer_af = GPIO_AF_TIM_3_4_5; + break; + /* Timers 6 and 7 don't have any capture/compare, so they + * can't do PWM (and in fact have no AF values). */ + case RCC_TIMER8: // fall-through + case RCC_TIMER9: // ... + case RCC_TIMER10: // ... + case RCC_TIMER11: + timer_af = GPIO_AF_TIM_8_9_10_11; + break; + case RCC_TIMER12: // fall-through + case RCC_TIMER13: // ... + case RCC_TIMER14: + timer_af = GPIO_AF_CAN_1_2_TIM_12_13_14; + break; + default: + ASSERT(0); // Can't happen + return; + } + timer_set_mode(info->timer_device, info->timer_channel, TIMER_PWM); + gpio_set_af(info->gpio_device, info->gpio_bit, timer_af); + } else { + gpio_set_modef(info->gpio_device, info->gpio_bit, mode, flags); + } +} diff --git a/wirish/wirish_digital.cpp b/wirish/wirish_digital.cpp index 6be1a29..a7f10cd 100644 --- a/wirish/wirish_digital.cpp +++ b/wirish/wirish_digital.cpp @@ -2,6 +2,7 @@ * The MIT License * * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2012 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -36,59 +37,6 @@ #include #include -void pinMode(uint8 pin, WiringPinMode mode) { - gpio_pin_mode outputMode; - bool pwm = false; - - if (pin >= BOARD_NR_GPIO_PINS) { - return; - } - - switch(mode) { - case OUTPUT: - outputMode = GPIO_OUTPUT_PP; - break; - case OUTPUT_OPEN_DRAIN: - outputMode = GPIO_OUTPUT_OD; - break; - case INPUT: - case INPUT_FLOATING: - outputMode = GPIO_INPUT_FLOATING; - break; - case INPUT_ANALOG: - outputMode = GPIO_INPUT_ANALOG; - break; - case INPUT_PULLUP: - outputMode = GPIO_INPUT_PU; - break; - case INPUT_PULLDOWN: - outputMode = GPIO_INPUT_PD; - break; - case PWM: - outputMode = GPIO_AF_OUTPUT_PP; - pwm = true; - break; - case PWM_OPEN_DRAIN: - outputMode = GPIO_AF_OUTPUT_OD; - pwm = true; - break; - default: - ASSERT(0); - return; - } - - gpio_set_mode(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, outputMode); - - if (PIN_MAP[pin].timer_device != NULL) { - /* Enable/disable timer channels if we're switching into or - * out of PWM. */ - timer_set_mode(PIN_MAP[pin].timer_device, - PIN_MAP[pin].timer_channel, - pwm ? TIMER_PWM : TIMER_DISABLED); - } -} - - uint32 digitalRead(uint8 pin) { if (pin >= BOARD_NR_GPIO_PINS) { return 0; -- cgit v1.2.3 From 1637300f8f751ccc17ff1a2f383c7fca902c0f8f Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Sat, 2 Jun 2012 21:02:34 -0400 Subject: Bring timer initialization back to init(). Turns out the F1 code was pretty portable after all, so take it from the F1 boards_setup.cpp and stick it back into boards.cpp. The only change needed was to add a call to the newly-minted timer_has_cc_channel() (and this is necessary on F103 XL-density, anyway). Also assert LeafLabs copyright in boards.cpp. We really need to do this throughout the library; it's basically been rewritten since Perry. Signed-off-by: Marti Bolivar --- wirish/boards.cpp | 43 ++++++++++++++++++++++++++++++++++++++- wirish/boards_private.h | 1 - wirish/stm32f1/boards_setup.cpp | 45 ----------------------------------------- wirish/stm32f2/boards_setup.cpp | 6 +----- 4 files changed, 43 insertions(+), 52 deletions(-) (limited to 'wirish/stm32f2') diff --git a/wirish/boards.cpp b/wirish/boards.cpp index 51ff50e..0faabfd 100644 --- a/wirish/boards.cpp +++ b/wirish/boards.cpp @@ -2,6 +2,7 @@ * The MIT License * * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011, 2012 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -55,6 +56,7 @@ static void setup_flash(void); static void setup_clocks(void); static void setup_nvic(void); static void setup_adcs(void); +static void setup_timers(void); /* * Exported functions @@ -67,7 +69,7 @@ void init(void) { systick_init(SYSTICK_RELOAD_VAL); wirish::priv::board_setup_gpio(); setup_adcs(); - wirish::priv::board_setup_timers(); + setup_timers(); wirish::priv::board_setup_usb(); boardInit(); } @@ -157,3 +159,42 @@ static void setup_adcs(void) { adc_set_prescaler(wirish::priv::w_adc_pre); adc_foreach(adc_default_config); } + +static void timer_default_config(timer_dev *dev) { + timer_adv_reg_map *regs = (dev->regs).adv; + const uint16 full_overflow = 0xFFFF; + const uint16 half_duty = 0x8FFF; + + timer_init(dev); + timer_pause(dev); + + regs->CR1 = TIMER_CR1_ARPE; + regs->PSC = 1; + regs->SR = 0; + regs->DIER = 0; + regs->EGR = TIMER_EGR_UG; + switch (dev->type) { + case TIMER_ADVANCED: + regs->BDTR = TIMER_BDTR_MOE | TIMER_BDTR_LOCK_OFF; + // fall-through + case TIMER_GENERAL: + timer_set_reload(dev, full_overflow); + for (uint8 channel = 1; channel <= 4; channel++) { + if (timer_has_cc_channel(dev, channel)) { + timer_set_compare(dev, channel, half_duty); + timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1, + TIMER_OC_PE); + } + } + // fall-through + case TIMER_BASIC: + break; + } + + timer_generate_update(dev); + timer_resume(dev); +} + +static void setup_timers(void) { + timer_foreach(timer_default_config); +} diff --git a/wirish/boards_private.h b/wirish/boards_private.h index e32f298..cdac844 100644 --- a/wirish/boards_private.h +++ b/wirish/boards_private.h @@ -58,7 +58,6 @@ namespace wirish { void board_reset_pll(void); void board_setup_clock_prescalers(void); void board_setup_gpio(void); - void board_setup_timers(void); void board_setup_usb(void); } diff --git a/wirish/stm32f1/boards_setup.cpp b/wirish/stm32f1/boards_setup.cpp index a71661d..423e5ec 100644 --- a/wirish/stm32f1/boards_setup.cpp +++ b/wirish/stm32f1/boards_setup.cpp @@ -62,8 +62,6 @@ namespace wirish { adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6; adc_smp_rate w_adc_smp = ADC_SMPR_55_5; - static void config_timer(timer_dev*); - void board_reset_pll(void) { // TODO } @@ -81,54 +79,11 @@ namespace wirish { afio_init(); } - void board_setup_timers(void) { - timer_foreach(config_timer); - } - void board_setup_usb(void) { #if 0 # if STM32_HAVE_USB usb_cdcacm_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT); # endif -#endif - } - - /* - * Auxiliary routines - */ - - static void config_timer(timer_dev *dev) { -#if 0 - timer_adv_reg_map *regs = (dev->regs).adv; - const uint16 full_overflow = 0xFFFF; - const uint16 half_duty = 0x8FFF; - - timer_init(dev); - timer_pause(dev); - - regs->CR1 = TIMER_CR1_ARPE; - regs->PSC = 1; - regs->SR = 0; - regs->DIER = 0; - regs->EGR = TIMER_EGR_UG; - - switch (dev->type) { - case TIMER_ADVANCED: - regs->BDTR = TIMER_BDTR_MOE | TIMER_BDTR_LOCK_OFF; - // fall-through - case TIMER_GENERAL: - timer_set_reload(dev, full_overflow); - - for (int channel = 1; channel <= 4; channel++) { - timer_set_compare(dev, channel, half_duty); - timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1, TIMER_OC_PE); - } - // fall-through - case TIMER_BASIC: - break; - } - - timer_resume(dev); #endif } } diff --git a/wirish/stm32f2/boards_setup.cpp b/wirish/stm32f2/boards_setup.cpp index e1bf1fd..9832bb7 100644 --- a/wirish/stm32f2/boards_setup.cpp +++ b/wirish/stm32f2/boards_setup.cpp @@ -81,12 +81,8 @@ namespace wirish { gpio_init_all(); } - void board_setup_timers(void) { - // TODO - } - void board_setup_usb(void) { - // TODO + // Nothing to do. } } -- cgit v1.2.3 From cc40b48edacdee58e56e443993aa3c1f22c9374e Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Sat, 2 Jun 2012 23:57:52 -0400 Subject: STM32F2: fix pinMode() for PWM, PWM_OPEN_DRAIN. Make it so the call to gpio_set_modef() actually happens. Signed-off-by: Marti Bolivar --- wirish/stm32f2/wirish_digital.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'wirish/stm32f2') diff --git a/wirish/stm32f2/wirish_digital.cpp b/wirish/stm32f2/wirish_digital.cpp index a67111d..bf9dcf5 100644 --- a/wirish/stm32f2/wirish_digital.cpp +++ b/wirish/stm32f2/wirish_digital.cpp @@ -124,7 +124,6 @@ void pinMode(uint8 pin, WiringPinMode w_mode) { } timer_set_mode(info->timer_device, info->timer_channel, TIMER_PWM); gpio_set_af(info->gpio_device, info->gpio_bit, timer_af); - } else { - gpio_set_modef(info->gpio_device, info->gpio_bit, mode, flags); } + gpio_set_modef(info->gpio_device, info->gpio_bit, mode, flags); } -- cgit v1.2.3 From ff56b76d41a390ed193da180316690f6e2dcbb75 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Sun, 3 Jun 2012 00:02:10 -0400 Subject: STM32F2: Add timer_get_af(). Pull some code out of the F2 pinMode() into a utility function. This feels generally useful enough to be exposed to the users (it will, for example, make it easier to implement input capture in a clean way). Signed-off-by: Marti Bolivar --- libmaple/stm32f2/include/series/timer.h | 7 +++++ libmaple/stm32f2/timer.c | 45 +++++++++++++++++++++++++++++++++ wirish/stm32f2/wirish_digital.cpp | 32 +---------------------- 3 files changed, 53 insertions(+), 31 deletions(-) (limited to 'wirish/stm32f2') diff --git a/libmaple/stm32f2/include/series/timer.h b/libmaple/stm32f2/include/series/timer.h index 0d959d0..ed473b4 100644 --- a/libmaple/stm32f2/include/series/timer.h +++ b/libmaple/stm32f2/include/series/timer.h @@ -34,6 +34,7 @@ #define _LIBMAPLE_STM32F2_TIMER_H_ #include +#include /* for gpio_af */ /* * Register maps and base pointers @@ -167,4 +168,10 @@ extern struct timer_dev *TIMER12; extern struct timer_dev *TIMER13; extern struct timer_dev *TIMER14; +/* + * Routines + */ + +gpio_af timer_get_af(struct timer_dev *dev); + #endif diff --git a/libmaple/stm32f2/timer.c b/libmaple/stm32f2/timer.c index 3f9a8d2..f644b16 100644 --- a/libmaple/stm32f2/timer.c +++ b/libmaple/stm32f2/timer.c @@ -114,6 +114,51 @@ void timer_foreach(void (*fn)(timer_dev*)) { fn(TIMER14); } +/** + * @brief Get the GPIO alternate function corresponding to a timer. + * + * For example, if dev is TIMER1, this function returns + * GPIO_AF_TIM_1_2. This is useful for e.g. using gpio_set_af() to set + * a pin's alternate function to a timer. + * + * Note that the timer gpio_afs are shared with other timers (and + * sometimes with CAN). For example, timers 1 and 2 both use + * GPIO_AF_TIM_1_2. Because of that, it can pay to e.g not point two + * timers at the same pin. + * + * @param dev Timer device, must not be TIMER6 or TIMER7. + * @return gpio_af corresponding to dev + * @see gpio_set_af + * @see gpio_af + */ +gpio_af timer_get_af(timer_dev *dev) { + rcc_clk_id clk_id = dev->clk_id; + /* Timers 6 and 7 don't have any capture/compare, so they can't do + * PWM (and in fact have no AF values). */ + ASSERT(clk_id != RCC_TIMER6 && clk_id != RCC_TIMER7); + switch(dev->clk_id) { + case RCC_TIMER1: // fall-through + case RCC_TIMER2: + return GPIO_AF_TIM_1_2; + case RCC_TIMER3: // fall-through + case RCC_TIMER4: // ... + case RCC_TIMER5: + return GPIO_AF_TIM_3_4_5; + case RCC_TIMER8: // fall-through + case RCC_TIMER9: // ... + case RCC_TIMER10: // ... + case RCC_TIMER11: + return GPIO_AF_TIM_8_9_10_11; + case RCC_TIMER12: // fall-through + case RCC_TIMER13: // ... + case RCC_TIMER14: + return GPIO_AF_CAN_1_2_TIM_12_13_14; + default: + ASSERT(0); // Can't happen + return (gpio_af)-1; + } +} + /* * IRQ handlers * diff --git a/wirish/stm32f2/wirish_digital.cpp b/wirish/stm32f2/wirish_digital.cpp index bf9dcf5..4d46f1c 100644 --- a/wirish/stm32f2/wirish_digital.cpp +++ b/wirish/stm32f2/wirish_digital.cpp @@ -91,37 +91,7 @@ void pinMode(uint8 pin, WiringPinMode w_mode) { if (info->timer_device == NULL) { return; } - gpio_af timer_af; - /* TODO make this code a convenience - * routine for series that support GPIO alternate - * functions. */ - switch(info->timer_device->clk_id) { - case RCC_TIMER1: // fall-through - case RCC_TIMER2: - timer_af = GPIO_AF_TIM_1_2; - break; - case RCC_TIMER3: // fall-through - case RCC_TIMER4: // ... - case RCC_TIMER5: - timer_af = GPIO_AF_TIM_3_4_5; - break; - /* Timers 6 and 7 don't have any capture/compare, so they - * can't do PWM (and in fact have no AF values). */ - case RCC_TIMER8: // fall-through - case RCC_TIMER9: // ... - case RCC_TIMER10: // ... - case RCC_TIMER11: - timer_af = GPIO_AF_TIM_8_9_10_11; - break; - case RCC_TIMER12: // fall-through - case RCC_TIMER13: // ... - case RCC_TIMER14: - timer_af = GPIO_AF_CAN_1_2_TIM_12_13_14; - break; - default: - ASSERT(0); // Can't happen - return; - } + gpio_af timer_af = timer_get_af(info->timer_device); timer_set_mode(info->timer_device, info->timer_channel, TIMER_PWM); gpio_set_af(info->gpio_device, info->gpio_bit, timer_af); } -- cgit v1.2.3 From b52f574dd6ec75157aebc48f1504832c0dd1c281 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Sun, 3 Jun 2012 21:00:14 -0400 Subject: STM32F2: Add SYSCFG support. Turn it on at init() time on F2. Signed-off-by: Marti Bolivar --- libmaple/include/libmaple/syscfg.h | 151 +++++++++++++++++++++++++++++++++++++ libmaple/stm32f2/rules.mk | 1 + libmaple/stm32f2/syscfg.c | 78 +++++++++++++++++++ wirish/boards.cpp | 10 ++- wirish/boards_private.h | 1 + wirish/stm32f2/boards_setup.cpp | 6 ++ 6 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 libmaple/include/libmaple/syscfg.h create mode 100644 libmaple/stm32f2/syscfg.c (limited to 'wirish/stm32f2') diff --git a/libmaple/include/libmaple/syscfg.h b/libmaple/include/libmaple/syscfg.h new file mode 100644 index 0000000..6b375d3 --- /dev/null +++ b/libmaple/include/libmaple/syscfg.h @@ -0,0 +1,151 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/syscfg.h + * @brief System configuration controller (SYSCFG) + * + * Availability: STM32F2, STM32F4. + */ + +#ifndef _LIBMAPLE_SYSCFG_H_ +#define _LIBMAPLE_SYSCFG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + * Register map and base pointer + */ + +/** + * @brief SYSCFG register map type. + */ +typedef struct syscfg_reg_map { + __io uint32 MEMRMP; /**< Memory remap register */ + __io uint32 PMC; /**< Peripheral mode configuration */ + __io uint32 EXTICR[4]; /**< External interrupt configuration registers */ + const uint32 RESERVED1; + const uint32 RESERVED2; + __io uint32 CMPCR; /**< Compensation cell control register */ +} syscfg_reg_map; + +/** SYSCFG register map base pointer */ +#define SYSCFG_BASE ((struct syscfg_reg_map*)0x40013800) + +/* + * Register bit definitions + */ + +/* Memory remap register */ + +#define SYSCFG_MEMRMP_MEM_MODE 0x3 +#define SYSCFG_MEMRMP_MEM_MODE_FLASH 0x0 +#define SYSCFG_MEMRMP_MEM_MODE_SYS_FLASH 0x1 +#define SYSCFG_MEMRMP_MEM_MODE_FSMC_1 0x2 +#define SYSCFG_MEMRMP_MEM_MODE_EMB_SRAM 0x3 + +/* Peripheral mode configuration register */ + +#define SYSCFG_PMC_MII_RMII_SEL_BIT 23 + +#define SYSCFG_PMC_MII_RMII_SEL (1U << SYSCFG_PMC_MII_RMII_SEL_BIT) +#define SYSCFG_PMC_MII_RMII_SEL_MII (0U << SYSCFG_PMC_MII_RMII_SEL_BIT) +#define SYSCFG_PMC_MII_RMII_SEL_RMII (1U << SYSCFG_PMC_MII_RMII_SEL_BIT) + +/* External interrupt configuration register 1 */ + +#define SYSCFG_EXTICR1_EXTI0 0xF +#define SYSCFG_EXTICR1_EXTI1 0xF0 +#define SYSCFG_EXTICR1_EXTI2 0xF00 +#define SYSCFG_EXTICR1_EXTI3 0xF000 + +/* External interrupt configuration register 2 */ + +#define SYSCFG_EXTICR2_EXTI4 0xF +#define SYSCFG_EXTICR2_EXTI5 0xF0 +#define SYSCFG_EXTICR2_EXTI6 0xF00 +#define SYSCFG_EXTICR2_EXTI7 0xF000 + +/* External interrupt configuration register 3 */ + +#define SYSCFG_EXTICR3_EXTI8 0xF +#define SYSCFG_EXTICR3_EXTI9 0xF0 +#define SYSCFG_EXTICR3_EXTI10 0xF00 +#define SYSCFG_EXTICR3_EXTI11 0xF000 + +/* External interrupt configuration register 4 */ + +#define SYSCFG_EXTICR4_EXTI12 0xF +#define SYSCFG_EXTICR4_EXTI13 0xF0 +#define SYSCFG_EXTICR4_EXTI14 0xF00 +#define SYSCFG_EXTICR4_EXTI15 0xF000 + +/* Compensation cell control register */ + +#define SYSCFG_CMPCR_READY_BIT 8 +#define SYSCFG_CMPCR_CMP_PD_BIT 0 + +#define SYSCFG_CMPCR_READY (1U << SYSCFG_CMPCR_READY_BIT) +#define SYSCFG_CMPCR_CMP_PD (1U << SYSCFG_CMPCR_CMP_PD_BIT) +#define SYSCFG_CMPCR_CMP_PD_PDWN (0U << SYSCFG_CMPCR_CMP_PD_BIT) +#define SYSCFG_CMPCR_CMP_PD_ENABLE (1U << SYSCFG_CMPCR_CMP_PD_BIT) + +/* + * Routines + */ + +void syscfg_init(void); + +void syscfg_enable_io_compensation(void); +void syscfg_disable_io_compensation(void); + +/** + * @brief System memory mode + * These values specify what memory to map to address 0x00000000. + * @see syscfg_set_mem_mode + */ +typedef enum syscfg_mem_mode { + /** Main flash memory is mapped at 0x0. */ + SYCFG_MEM_MODE_FLASH = SYSCFG_MEMRMP_MEM_MODE_FLASH, + /** System flash (i.e. ST's baked-in bootloader) is mapped at 0x0. */ + SYCFG_MEM_MODE_SYSTEM_FLASH = SYSCFG_MEMRMP_MEM_MODE_SYS_FLASH, + /** FSMC bank 1 (NOR/PSRAM 1 and 2) is mapped at 0x0. */ + SYCFG_MEM_MODE_FSMC_BANK_1 = SYSCFG_MEMRMP_MEM_MODE_FSMC_1, + /** Embedded SRAM (i.e., not backup SRAM) is mapped at 0x0. */ + SYCFG_MEM_MODE_SRAM = SYSCFG_MEMRMP_MEM_MODE_EMB_SRAM, +} syscfg_mem_mode; + +void syscfg_set_mem_mode(syscfg_mem_mode); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmaple/stm32f2/rules.mk b/libmaple/stm32f2/rules.mk index c98f5b9..a5be551 100644 --- a/libmaple/stm32f2/rules.mk +++ b/libmaple/stm32f2/rules.mk @@ -15,6 +15,7 @@ cSRCS_$(d) := adc.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c cSRCS_$(d) += rcc.c +cSRCS_$(d) += syscfg.c cSRCS_$(d) += timer.c cSRCS_$(d) += usart.c diff --git a/libmaple/stm32f2/syscfg.c b/libmaple/stm32f2/syscfg.c new file mode 100644 index 0000000..19e932e --- /dev/null +++ b/libmaple/stm32f2/syscfg.c @@ -0,0 +1,78 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/syscfg.c + * @brief SYSCFG routines. + */ + +#include +#include +#include + +/** + * @brief Initialize the SYSCFG peripheral. + */ +void syscfg_init(void) { + rcc_clk_enable(RCC_SYSCFG); + rcc_reset_dev(RCC_SYSCFG); +} + +/** + * @brief Turn on the I/O compensation cell. + * + * It's only safe to do this when the supply voltage is between 2.4 V + * and 3.6 V. + */ +void syscfg_enable_io_compensation(void) { + bb_peri_set_bit(&SYSCFG_BASE->CMPCR, SYSCFG_CMPCR_CMP_PD_BIT, 1); + while (!(SYSCFG_BASE->CMPCR & SYSCFG_CMPCR_READY)) + ; +} + +/** + * @brief Turn off the I/O compensation cell. + */ +void syscfg_disable_io_compensation(void) { + bb_peri_set_bit(&SYSCFG_BASE->CMPCR, SYSCFG_CMPCR_CMP_PD_BIT, 0); +} + +/** + * @brief Set the memory to be mapped at address 0x00000000. + * + * This function can be used to override the BOOT pin + * configuration. Some restrictions apply; see your chip's reference + * manual for the details. + * + * @param mode Mode to set + * @see syscfg_mem_mode + */ +void syscfg_set_mem_mode(syscfg_mem_mode mode) { + uint32 memrmp = SYSCFG_BASE->MEMRMP; + memrmp &= ~SYSCFG_MEMRMP_MEM_MODE; + memrmp |= (uint32)mode; + SYSCFG_BASE->MEMRMP = memrmp; +} diff --git a/wirish/boards.cpp b/wirish/boards.cpp index 7616245..471325f 100644 --- a/wirish/boards.cpp +++ b/wirish/boards.cpp @@ -71,10 +71,18 @@ void init(void) { setup_adcs(); setup_timers(); wirish::priv::board_setup_usb(); + wirish::priv::series_init(); boardInit(); } -/* Provide a default boardInit(). */ +/* Provide a default no-op series_init() */ +namespace wirish { + namespace priv { + __weak void series_init(void) {} + } +} + +/* Provide a default no-op boardInit(). */ __weak void boardInit(void) { } diff --git a/wirish/boards_private.h b/wirish/boards_private.h index cdac844..4607913 100644 --- a/wirish/boards_private.h +++ b/wirish/boards_private.h @@ -59,6 +59,7 @@ namespace wirish { void board_setup_clock_prescalers(void); void board_setup_gpio(void); void board_setup_usb(void); + void series_init(void); } } diff --git a/wirish/stm32f2/boards_setup.cpp b/wirish/stm32f2/boards_setup.cpp index 9832bb7..d1ceac0 100644 --- a/wirish/stm32f2/boards_setup.cpp +++ b/wirish/stm32f2/boards_setup.cpp @@ -37,6 +37,7 @@ #include "boards_private.h" #include +#include #include // PLL configuration for 25 MHz external oscillator --> 120 MHz SYSCLK. @@ -85,5 +86,10 @@ namespace wirish { // Nothing to do. } + void series_init(void) { + // We need SYSCFG for external interrupts + syscfg_init(); + } + } } -- cgit v1.2.3 From 2bdf250ecdd0a30aae6f582aa92e5b3e53835a67 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Sun, 3 Jun 2012 22:31:34 -0400 Subject: STM32F2: Turn on SYSCFG I/O compensation during init(). Signed-off-by: Marti Bolivar --- wirish/stm32f2/boards_setup.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'wirish/stm32f2') diff --git a/wirish/stm32f2/boards_setup.cpp b/wirish/stm32f2/boards_setup.cpp index d1ceac0..952e84d 100644 --- a/wirish/stm32f2/boards_setup.cpp +++ b/wirish/stm32f2/boards_setup.cpp @@ -89,6 +89,9 @@ namespace wirish { void series_init(void) { // We need SYSCFG for external interrupts syscfg_init(); + // Turn on the I/O compensation cell, since we drive the + // GPIOs quickly be default. + syscfg_enable_io_compensation(); } } -- cgit v1.2.3 From b12b8e7c24487c183d73fed4d7848a4bd0e8304a Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 5 Jun 2012 15:07:01 -0400 Subject: wirish: Weaken boards_private.h definitions. This lets users override them conveniently if our decisions don't suit. Signed-off-by: Marti Bolivar --- wirish/stm32f1/boards_setup.cpp | 16 +++++++------- wirish/stm32f2/boards_setup.cpp | 48 ++++++++++++++++++++++++----------------- 2 files changed, 36 insertions(+), 28 deletions(-) (limited to 'wirish/stm32f2') diff --git a/wirish/stm32f1/boards_setup.cpp b/wirish/stm32f1/boards_setup.cpp index d224ef2..11872d5 100644 --- a/wirish/stm32f1/boards_setup.cpp +++ b/wirish/stm32f1/boards_setup.cpp @@ -55,31 +55,31 @@ namespace wirish { namespace priv { static stm32f1_rcc_pll_data pll_data = {BOARD_RCC_PLLMUL}; - rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; - adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6; - adc_smp_rate w_adc_smp = ADC_SMPR_55_5; + __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; + __weak adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6; + __weak adc_smp_rate w_adc_smp = ADC_SMPR_55_5; - void board_reset_pll(void) { + __weak void board_reset_pll(void) { // TODO } - void board_setup_clock_prescalers(void) { + __weak void board_setup_clock_prescalers(void) { rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1); rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_2); rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_1); } - void board_setup_gpio(void) { + __weak void board_setup_gpio(void) { gpio_init_all(); } - void board_setup_usb(void) { + __weak void board_setup_usb(void) { #if BOARD_HAVE_SERIALUSB SerialUSB.begin(); #endif } - void series_init(void) { + __weak void series_init(void) { // Initialize AFIO here, too, so peripheral remaps and external // interrupts work out of the box. afio_init(); diff --git a/wirish/stm32f2/boards_setup.cpp b/wirish/stm32f2/boards_setup.cpp index 952e84d..876a65b 100644 --- a/wirish/stm32f2/boards_setup.cpp +++ b/wirish/stm32f2/boards_setup.cpp @@ -38,6 +38,7 @@ #include #include +#include #include // PLL configuration for 25 MHz external oscillator --> 120 MHz SYSCLK. @@ -50,43 +51,50 @@ static stm32f2_rcc_pll_data pll_data = {PLL_Q, PLL_P, PLL_N, PLL_M}; namespace wirish { namespace priv { // PLL clocked off of HSE, with above configuration data. - rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; - // As f_APB2 = 60 MHz (see board_setup_clock_prescalers), - // we need f_ADC = f_PCLK2 / 2 to get the (maximum) - // f_ADC = 30 MHz. - adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_2; - // With clocks as specified here (i.e. f_ADC = 30 MHz), this - // ADC sample rate allows for error less than 1/4 LSB with a - // 50 KOhm input impedance, assuming an internal sample and - // hold capacitance C_ADC at most 8.8 pF. See Equation 1 and - // Table 61 in the F2 datasheet for more details. - adc_smp_rate w_adc_smp = ADC_SMPR_144; + __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; - void board_reset_pll(void) { + // Global ADC prescaler + // + // On F2, with f_APB2 = 60 MHz, we need f_ADC = f_PCLK2 / 2 to + // get the (maximum) f_ADC = 30 MHz. + __weak adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_2; + + // Conservative ADC sample rate. Goal is error less than 1/4 + // LSB with 50 KOhm input impedance. + // + // On F2, with f_ADC = 30 MHz, error is acceptable assuming an + // internal sample and hold capacitance C_ADC at most 8.8 pF + // (ST doesn't specify the maximum C_ADC, so we had to take a + // guess). See Equation 1 and Table 61 in the F2 datasheet for + // more details. + __weak adc_smp_rate w_adc_smp = ADC_SMPR_144; + + __weak void board_reset_pll(void) { // Set PLLCFGR to its reset value. RCC_BASE->PLLCFGR = 0x24003010; // FIXME lose the magic number. } - void board_setup_clock_prescalers(void) { - // With f_SYSCLK = 120 MHz (as determined by board_pll_cfg), + __weak void board_setup_clock_prescalers(void) { + // On F2, with f_SYSCLK = 120 MHz (as determined by + // board_pll_cfg), // - // f_AHB = f_SYSCLK / 1 = 120 MHz + // f_AHB = f_SYSCLK / 1 = 120 MHz + // f_APB1 = f_AHB / 4 = 30 MHz + // f_APB2 = f_AHB / 2 = 60 MHz rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1); - // f_APB1 = f_AHB / 4 = 30 MHz rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_4); - // f_APB2 = f_AHB / 2 = 60 MHz rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_2); } - void board_setup_gpio(void) { + __weak void board_setup_gpio(void) { gpio_init_all(); } - void board_setup_usb(void) { + __weak void board_setup_usb(void) { // Nothing to do. } - void series_init(void) { + __weak void series_init(void) { // We need SYSCFG for external interrupts syscfg_init(); // Turn on the I/O compensation cell, since we drive the -- cgit v1.2.3 From adbbbc19369f64d64f72d9417a0bf0272d1ba497 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 5 Jun 2012 17:50:18 -0400 Subject: STM32F2: Allow boards to override PLL configuration. Signed-off-by: Marti Bolivar --- wirish/stm32f2/boards_setup.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'wirish/stm32f2') diff --git a/wirish/stm32f2/boards_setup.cpp b/wirish/stm32f2/boards_setup.cpp index 876a65b..dd872d3 100644 --- a/wirish/stm32f2/boards_setup.cpp +++ b/wirish/stm32f2/boards_setup.cpp @@ -40,13 +40,27 @@ #include #include #include +#include -// PLL configuration for 25 MHz external oscillator --> 120 MHz SYSCLK. -#define PLL_Q 5 -#define PLL_P 2 -#define PLL_N 240 -#define PLL_M 25 -static stm32f2_rcc_pll_data pll_data = {PLL_Q, PLL_P, PLL_N, PLL_M}; +// PLL config for 25 MHz external crystal --> 120 MHz SYSCLK, with +// 48 MHz PLL48CK. +#ifndef BOARD_PLL_Q +#define BOARD_PLL_Q 5 +#endif +#ifndef BOARD_PLL_P +#define BOARD_PLL_P 2 +#endif +#ifndef BOARD_PLL_N +#define BOARD_PLL_N 240 +#endif +#ifndef BOARD_PLL_M +#define BOARD_PLL_M 25 +#endif + +static stm32f2_rcc_pll_data pll_data = {BOARD_PLL_Q, + BOARD_PLL_P, + BOARD_PLL_N, + BOARD_PLL_M}; namespace wirish { namespace priv { -- cgit v1.2.3 From 3193ae1326c738b54067674a6073287f90ecaa85 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Fri, 8 Jun 2012 18:34:33 -0400 Subject: Bring back . Signed-off-by: Marti Bolivar --- wirish/include/wirish/wirish.h | 2 +- wirish/include/wirish/wirish_debug.h | 8 ++--- wirish/rules.mk | 1 + wirish/stm32f1/wirish_debug.cpp | 41 ++++++++++++++++++++++++ wirish/stm32f2/wirish_debug.cpp | 60 ++++++++++++++++++++++++++++++++++++ 5 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 wirish/stm32f1/wirish_debug.cpp create mode 100644 wirish/stm32f2/wirish_debug.cpp (limited to 'wirish/stm32f2') diff --git a/wirish/include/wirish/wirish.h b/wirish/include/wirish/wirish.h index 6810e4f..360b502 100644 --- a/wirish/include/wirish/wirish.h +++ b/wirish/include/wirish/wirish.h @@ -39,7 +39,7 @@ #include #include #include -/* FIXME put this back when you can #include */ +#include #include #include /* FIXME put this back when you can #include */ diff --git a/wirish/include/wirish/wirish_debug.h b/wirish/include/wirish/wirish_debug.h index cb1be3d..4edfd27 100644 --- a/wirish/include/wirish/wirish_debug.h +++ b/wirish/include/wirish/wirish_debug.h @@ -42,9 +42,7 @@ * * @see enableDebugPorts() */ -static inline void disableDebugPorts(void) { - afio_cfg_debug_ports(AFIO_DEBUG_NONE); -} +void disableDebugPorts(void); /** * @brief Enable the JTAG and Serial Wire (SW) debug ports. @@ -54,8 +52,6 @@ static inline void disableDebugPorts(void) { * * @see disableDebugPorts() */ -static inline void enableDebugPorts(void) { - afio_cfg_debug_ports(AFIO_DEBUG_FULL_SWJ); -} +void enableDebugPorts(void); #endif diff --git a/wirish/rules.mk b/wirish/rules.mk index acf4c46..5138c82 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -38,6 +38,7 @@ cppSRCS_$(d) += wirish_shift.cpp cppSRCS_$(d) += wirish_time.cpp cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp +cppSRCS_$(d) += $(MCU_SERIES)/wirish_debug.cpp cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp # TODO: revise these appropriately for F2 and put them back in: # HardwareSPI.cpp diff --git a/wirish/stm32f1/wirish_debug.cpp b/wirish/stm32f1/wirish_debug.cpp new file mode 100644 index 0000000..28de96d --- /dev/null +++ b/wirish/stm32f1/wirish_debug.cpp @@ -0,0 +1,41 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file wirish/stm32f1/wirish_debug.cpp + * @brief High level debug port configuration + */ + +#include +#include + +void disableDebugPorts(void) { + afio_cfg_debug_ports(AFIO_DEBUG_NONE); +} + +void enableDebugPorts(void) { + afio_cfg_debug_ports(AFIO_DEBUG_FULL_SWJ); +} diff --git a/wirish/stm32f2/wirish_debug.cpp b/wirish/stm32f2/wirish_debug.cpp new file mode 100644 index 0000000..af6c78b --- /dev/null +++ b/wirish/stm32f2/wirish_debug.cpp @@ -0,0 +1,60 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file wirish/stm32f2/wirish_debug.cpp + * @brief High level debug port configuration + */ + +#include +#include + +// TODO is it worth optimizing these into raw MODER and AFR[LH] writes? + +void disableDebugPorts(void) { + // PA13-PA15 and PB3-PB4 are in system alternate function mode on + // reset, to support JTAG. Just put them in input mode to release + // them. + gpio_set_mode(GPIOA, 13, GPIO_MODE_INPUT); + gpio_set_mode(GPIOA, 14, GPIO_MODE_INPUT); + gpio_set_mode(GPIOA, 15, GPIO_MODE_INPUT); + gpio_set_mode(GPIOB, 3, GPIO_MODE_INPUT); + gpio_set_mode(GPIOB, 4, GPIO_MODE_INPUT); +} + +void enableDebugPorts(void) { + // Put PA13-PA15 and PB3-PB4 back in system AF mode. + gpio_set_mode(GPIOA, 13, GPIO_MODE_AF); + gpio_set_mode(GPIOA, 14, GPIO_MODE_AF); + gpio_set_mode(GPIOA, 15, GPIO_MODE_AF); + gpio_set_mode(GPIOB, 3, GPIO_MODE_AF); + gpio_set_mode(GPIOB, 4, GPIO_MODE_AF); + gpio_set_af(GPIOA, 13, GPIO_AF_SYS); + gpio_set_af(GPIOA, 14, GPIO_AF_SYS); + gpio_set_af(GPIOA, 15, GPIO_AF_SYS); + gpio_set_af(GPIOB, 3, GPIO_AF_SYS); + gpio_set_af(GPIOB, 4, GPIO_AF_SYS); +} -- cgit v1.2.3 From 24c77dbcb09e20f9d4b0e4c7bfc7b8c27809f931 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 7 Jun 2012 22:47:49 -0400 Subject: Typo fix. Signed-off-by: Marti Bolivar --- wirish/stm32f2/boards_setup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wirish/stm32f2') diff --git a/wirish/stm32f2/boards_setup.cpp b/wirish/stm32f2/boards_setup.cpp index dd872d3..5764dd0 100644 --- a/wirish/stm32f2/boards_setup.cpp +++ b/wirish/stm32f2/boards_setup.cpp @@ -112,7 +112,7 @@ namespace wirish { // We need SYSCFG for external interrupts syscfg_init(); // Turn on the I/O compensation cell, since we drive the - // GPIOs quickly be default. + // GPIOs quickly by default. syscfg_enable_io_compensation(); } -- cgit v1.2.3 From fbbf35ee079d1c979909981c95132ba7eaca7215 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 26 Jun 2012 18:03:40 -0400 Subject: Bring back and fix up util.c functionality. Rip out the existing nonportable pieces, and shove them under wirish/stm32f1, using weak symbols so users who only want libmaple proper don't end up with build errors. Add stubbed-out (and only partially functional) definitions for F2 targets under wirish/stm32f2. The behavior on F103 targets is the same as it was before (though the assertion framework has always been broken and badly needs replacement, that awaits another commit). We additionally now skip re-enabling USB on F1 targets without USB, to make things work on value line MCUs. Signed-off-by: Marti Bolivar --- libmaple/util.c | 119 ++++++++++++++++---------------------------- wirish/rules.mk | 1 + wirish/stm32f1/util_hooks.c | 83 ++++++++++++++++++++++++++++++ wirish/stm32f2/util_hooks.c | 45 +++++++++++++++++ 4 files changed, 171 insertions(+), 77 deletions(-) create mode 100644 wirish/stm32f1/util_hooks.c create mode 100644 wirish/stm32f2/util_hooks.c (limited to 'wirish/stm32f2') diff --git a/libmaple/util.c b/libmaple/util.c index 88da075..2ee5ede 100644 --- a/libmaple/util.c +++ b/libmaple/util.c @@ -26,27 +26,17 @@ /** * @file libmaple/util.c - * @brief Utility procedures for debugging, mostly an error LED fade - * and messages dumped over a UART for failed asserts. + * @brief Utility procedures for debugging */ #include #include #include #include -#include -#include -/* FIXME [0.0.13] put this stuff back in some form. Move to Wirish? */ - -/* Failed ASSERT()s send out a message using this USART config. */ -#ifndef ERROR_USART -#define ERROR_USART USART2 -#define ERROR_USART_CLK_SPEED STM32_PCLK1 -#define ERROR_USART_BAUD 9600 -#define ERROR_TX_PORT GPIOA -#define ERROR_TX_PIN 2 -#endif +/* (Undocumented) hooks used by Wirish to direct our behavior here */ +extern __weak void __lm_error(void); +extern __weak usart_dev* __lm_enable_error_usart(void); /* If you define ERROR_LED_PORT and ERROR_LED_PIN, then a failed * ASSERT() will also throb() an LED connected to that port and pin. @@ -55,100 +45,75 @@ #define HAVE_ERROR_LED #endif -/** - * @brief Disables all peripheral interrupts except USB and fades the - * error LED. - */ /* (Called from exc.S with global interrupts disabled.) */ -void __error(void) { - /* Turn off peripheral interrupts */ - nvic_irq_disable_all(); - - /* /\* Turn off timers *\/ */ - /* timer_disable_all(); */ - - /* /\* Turn off ADC *\/ */ - /* adc_disable_all(); */ - - /* /\* Turn off all USARTs *\/ */ - /* usart_disable_all(); */ - - /* /\* Turn the USB interrupt back on so the bootloader keeps on functioning *\/ */ - /* nvic_irq_enable(NVIC_USB_HP_CAN_TX); */ - /* nvic_irq_enable(NVIC_USB_LP_CAN_RX0); */ - +__attribute__((noreturn)) void __error(void) { + if (__lm_error) { + __lm_error(); + } /* Reenable global interrupts */ nvic_globalirq_enable(); throb(); } -/** - * @brief Enable the error USART for writing. - * @sideeffect Configures ERROR_USART appropriately for writing. - */ -void _enable_error_usart() { - /* gpio_set_mode(ERROR_TX_PORT, ERROR_TX_PIN, GPIO_AF_OUTPUT_PP); */ - /* usart_init(ERROR_USART); */ - /* usart_set_baud_rate(ERROR_USART, ERROR_USART_CLK_SPEED, ERROR_USART_BAUD); */ -} - -/** - * @brief Print an error message on a UART upon a failed assertion - * and throb the error LED, if there is one defined. +/* + * Print an error message on a UART upon a failed assertion (if one is + * available), and punt to __error(). + * * @param file Source file of failed assertion * @param line Source line of failed assertion * @param exp String representation of failed assertion * @sideeffect Turns of all peripheral interrupts except USB. */ void _fail(const char* file, int line, const char* exp) { - /* Initialize the error USART */ - /* _enable_error_usart(); */ - - /* /\* Print failed assert message *\/ */ - /* usart_putstr(ERROR_USART, "ERROR: FAILED ASSERT("); */ - /* usart_putstr(ERROR_USART, exp); */ - /* usart_putstr(ERROR_USART, "): "); */ - /* usart_putstr(ERROR_USART, file); */ - /* usart_putstr(ERROR_USART, ": "); */ - /* usart_putudec(ERROR_USART, line); */ - /* usart_putc(ERROR_USART, '\n'); */ - /* usart_putc(ERROR_USART, '\r'); */ - + if (__lm_enable_error_usart) { + /* Initialize the error USART */ + usart_dev *err_usart = __lm_enable_error_usart(); + + /* Print failed assert message */ + usart_putstr(err_usart, "ERROR: FAILED ASSERT("); + usart_putstr(err_usart, exp); + usart_putstr(err_usart, "): "); + usart_putstr(err_usart, file); + usart_putstr(err_usart, ": "); + usart_putudec(err_usart, line); + usart_putc(err_usart, '\n'); + usart_putc(err_usart, '\r'); + } /* Shutdown and error fade */ __error(); } -/** - * @brief Provide an __assert_func handler to libc so that calls to assert() get - * redirected to _fail. +/* + * Provide an __assert_func handler to libc so that calls to assert() + * get redirected to _fail. */ void __assert_func(const char* file, int line, const char* method, const char* expression) { _fail(file, line, expression); } -/** - * @brief Provide an abort() implementation that aborts execution and enters an - * error state with the throbbing LED indicator. +/* + * Provide an abort() implementation that aborts execution and punts + * to __error(). */ void abort() { - /* /\* Initialize the error USART *\/ */ - /* _enable_error_usart(); */ - - /* /\* Print abort message. *\/ */ - /* usart_putstr(ERROR_USART, "ERROR: PROGRAM ABORTED VIA abort()\n\r"); */ + if (__lm_enable_error_usart) { + /* Initialize the error USART */ + usart_dev *err_usart = __lm_enable_error_usart(); + /* Print abort message. */ + usart_putstr(err_usart, "ERROR: PROGRAM ABORTED VIA abort()\r\n"); + } - /* /\* Shutdown and error fade *\/ */ - /* __error(); */ - while (1) - ; + /* Shutdown and error fade */ + __error(); } +/* This was public as of v0.0.12, so we've got to keep it public. */ /** * @brief Fades the error LED on and off * @sideeffect Sets output push-pull on ERROR_LED_PIN. */ -void throb(void) { +__attribute__((noreturn)) void throb(void) { #ifdef HAVE_ERROR_LED int32 slope = 1; uint32 CC = 0x0000; diff --git a/wirish/rules.mk b/wirish/rules.mk index 5138c82..f895213 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -21,6 +21,7 @@ CFLAGS_$(d) := $(LIBMAPLE_INCLUDES) $(WIRISH_INCLUDES) -I$(d) sSRCS_$(d) := start.S cSRCS_$(d) := start_c.c cSRCS_$(d) += syscalls.c +cSRCS_$(d) += $(MCU_SERIES)/util_hooks.c cppSRCS_$(d) := boards.cpp cppSRCS_$(d) += cxxabi-compat.cpp cppSRCS_$(d) += ext_interrupts.cpp diff --git a/wirish/stm32f1/util_hooks.c b/wirish/stm32f1/util_hooks.c new file mode 100644 index 0000000..8f798a1 --- /dev/null +++ b/wirish/stm32f1/util_hooks.c @@ -0,0 +1,83 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung (from libmaple/util.c). + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/* + * STM32F1 implementations for libmaple/util.c hooks + * + * These need more love and attention before being made public API + * (this includes being easily overridable by user code). + */ + +#include +#include +#include +#include +#include +#include + +/* Failed ASSERT()s send out a message using this USART config. */ +#ifndef ERROR_USART +#define ERROR_USART USART2 +#define ERROR_USART_BAUD 9600 +#define ERROR_TX_PORT GPIOA +#define ERROR_TX_PIN 2 +#endif + +/* + * Disables all peripheral interrupts except USB (when available), + * turns off commonly-used peripherals. Called by __error() with + * global interrupts disabled. + */ +void __lm_error(void) { + /* Turn off peripheral interrupts */ + nvic_irq_disable_all(); + + /* Turn off timers */ + timer_disable_all(); + + /* Turn off ADC */ + adc_disable_all(); + + /* Turn off all USARTs */ + usart_disable_all(); + +#if STM32_HAVE_USB + /* Turn the USB interrupt back on so the bootloader keeps on functioning */ + nvic_irq_enable(NVIC_USB_HP_CAN_TX); + nvic_irq_enable(NVIC_USB_LP_CAN_RX0); +#endif +} + +/* + * Enable the error USART for writing. + */ +usart_dev* __lm_enable_error_usart() { + gpio_set_mode(ERROR_TX_PORT, ERROR_TX_PIN, GPIO_AF_OUTPUT_PP); + usart_init(ERROR_USART); + usart_set_baud_rate(ERROR_USART, USART_USE_PCLK, ERROR_USART_BAUD); + return ERROR_USART; +} diff --git a/wirish/stm32f2/util_hooks.c b/wirish/stm32f2/util_hooks.c new file mode 100644 index 0000000..1b519ab --- /dev/null +++ b/wirish/stm32f2/util_hooks.c @@ -0,0 +1,45 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/* + * STM32F2 implementations for libmaple util.c hooks + * FIXME these are just minimal stubs + */ + +#include + +/* + * Disables all peripheral interrupts. Called by __error() with global + * interrupts disabled. + */ +void __lm_error(void) { + nvic_irq_disable_all(); +} + +/* + * Enable the error USART for writing. + */ +/* usart_dev* __lm_enable_error_usart(void) { (TODO) } */ -- cgit v1.2.3