From a5b5d4f27f94befaf5577563a0319e8194377118 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Sun, 3 Jun 2012 20:30:13 -0400 Subject: Bring back EXTI on F1, with deprecations for gpio.h on F1. Tested on Maple Mini with examples/mini-exti-test. Changes to Wirish are minor: use the new EXTI types exti_num and exti_cfg (see below) in place of now-deprecated variants in ext_interrupts.cpp. The way I originally did libmaple/exti.h was stupid, and fixing it turned out to be a little disruptive. libmaple/exti.h depends on libmaple/gpio.h (for AFIO), but that's a classic case of exposed implementation detail. So invert the dependency: make gpio.h depend on exti.h. Do this by adding exti_num and exti_cfg to exti.h; these respectively replace afio_exti_num and afio_exti_port. The afio_* variants are now deprecated. (Throw in a typedef and some macros at the bottom of the F1 series/gpio.h for backwards compatibility). Make exti_attach_interrupt() and exti_detach_interrupt() take exti_num/exti_cfg arguments instead of the afio_* variants. Make the EXTI dispatch routines __always_inline to defeat GCC -Os. Many renames throughout libmaple/stm32f1/ to stop using the deprecated names. Also move the previously F1-only gpio_exti_port() function into the public libmaple header. Reimplementing it in terms of rcc_clk_ids lets us deprecate the gpio_dev->exti_port field, which will save space in the future. While we're there, I notice that struct gpio_dev is defined once per series. That's dumb, as it misses the entire point of having device structs: they contain what's portable. So put the F1 version (which has the extra EXTI port field) into libmaple/gpio.h, and add the necessary exti_ports to libmaple/stm32f2/gpio.c. Sigh. We'll get rid of it eventually, at least. Clean up some other mistakes in gpio.h files as well (mostly removing util.h dependency). Sorry for the messy commit. For portability, add a new series-specific exti function, exti_select(). The F1 version in (new) libmaple/stm32f1/exti.c uses AFIO and some new private functionality in libmaple/exti.c and (new) libmaple/exti_private.h to make this convenient. We'll be able to do the SYSCFG equivalent on F2 without any trouble. Signed-off-by: Marti Bolivar --- libmaple/exti.c | 58 ++++++--- libmaple/exti_private.h | 34 ++++++ libmaple/include/libmaple/exti.h | 78 +++++++++++- libmaple/include/libmaple/gpio.h | 41 +++++-- libmaple/rules.mk | 2 +- libmaple/stm32f1/exti.c | 32 +++++ libmaple/stm32f1/gpio.c | 36 ++---- libmaple/stm32f1/include/series/gpio.h | 215 ++++++++++++++++++--------------- libmaple/stm32f1/rules.mk | 1 + libmaple/stm32f2/gpio.c | 9 ++ libmaple/stm32f2/include/series/gpio.h | 54 ++++----- 11 files changed, 372 insertions(+), 188 deletions(-) create mode 100644 libmaple/exti_private.h create mode 100644 libmaple/stm32f1/exti.c (limited to 'libmaple') diff --git a/libmaple/exti.c b/libmaple/exti.c index 248c4b6..d84b789 100644 --- a/libmaple/exti.c +++ b/libmaple/exti.c @@ -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 @@ -66,7 +67,7 @@ static exti_channel exti_channels[] = { }; /* - * Convenience routines + * Portable routines */ /** @@ -80,13 +81,13 @@ static exti_channel exti_channels[] = { * @param handler Function handler to execute when interrupt is triggered. * @param mode Type of transition to trigger on, one of: * EXTI_RISING, EXTI_FALLING, EXTI_RISING_FALLING. - * @see afio_exti_num - * @see afio_exti_port + * @see exti_num + * @see exti_cfg * @see voidFuncPtr * @see exti_trigger_mode */ -void exti_attach_interrupt(afio_exti_num num, - afio_exti_port port, +void exti_attach_interrupt(exti_num num, + exti_cfg port, voidFuncPtr handler, exti_trigger_mode mode) { ASSERT(handler); @@ -108,8 +109,8 @@ void exti_attach_interrupt(afio_exti_num num, break; } - /* Map num to port */ - afio_exti_select(num, port); + /* Use the chip-specific exti_select() to map num to port */ + exti_select(num, port); /* Unmask external interrupt request */ bb_peri_set_bit(&EXTI_BASE->IMR, num, 1); @@ -120,10 +121,10 @@ void exti_attach_interrupt(afio_exti_num num, /** * @brief Unregister an external interrupt handler - * @param num Number of the external interrupt line to disable. - * @see afio_exti_num + * @param num External interrupt line to disable. + * @see exti_num */ -void exti_detach_interrupt(afio_exti_num num) { +void exti_detach_interrupt(exti_num num) { /* First, mask the interrupt request */ bb_peri_set_bit(&EXTI_BASE->IMR, num, 0); @@ -135,28 +136,45 @@ void exti_detach_interrupt(afio_exti_num num) { exti_channels[num].handler = NULL; } +/* Weak default exti_select(), until we get F2 support */ +__weak void exti_select(exti_num num, exti_cfg port) { + ASSERT(0); +} + +/* + * Private routines + */ + +void exti_do_select(__io uint32 *exti_cr, exti_num num, exti_cfg port) { + uint32 shift = 4 * (num % 4); + uint32 cr = *exti_cr; + cr &= ~(0xF << shift); + cr |= port << shift; + *exti_cr = cr; +} + /* * Interrupt handlers */ void __irq_exti0(void) { - dispatch_single_exti(AFIO_EXTI_0); + dispatch_single_exti(EXTI0); } void __irq_exti1(void) { - dispatch_single_exti(AFIO_EXTI_1); + dispatch_single_exti(EXTI1); } void __irq_exti2(void) { - dispatch_single_exti(AFIO_EXTI_2); + dispatch_single_exti(EXTI2); } void __irq_exti3(void) { - dispatch_single_exti(AFIO_EXTI_3); + dispatch_single_exti(EXTI3); } void __irq_exti4(void) { - dispatch_single_exti(AFIO_EXTI_4); + dispatch_single_exti(EXTI4); } void __irq_exti9_5(void) { @@ -177,7 +195,7 @@ void __irq_exti15_10(void) { * won't actually be cleared in time and the ISR will fire again. To * compensate, this function NOPs for 2 cycles after clearing the * pending bits to ensure it takes effect. */ -static inline void clear_pending_msk(uint32 exti_msk) { +static __always_inline void clear_pending_msk(uint32 exti_msk) { EXTI_BASE->PR = exti_msk; asm volatile("nop"); asm volatile("nop"); @@ -185,7 +203,7 @@ static inline void clear_pending_msk(uint32 exti_msk) { /* This dispatch routine is for non-multiplexed EXTI lines only; i.e., * it doesn't check EXTI_PR. */ -static inline void dispatch_single_exti(uint32 exti) { +static __always_inline void dispatch_single_exti(uint32 exti) { voidFuncPtr handler = exti_channels[exti].handler; if (!handler) { @@ -193,18 +211,18 @@ static inline void dispatch_single_exti(uint32 exti) { } handler(); - clear_pending_msk(BIT(exti)); + clear_pending_msk(1U << exti); } /* Dispatch routine for EXTIs which share an IRQ. */ -static inline void dispatch_extis(uint32 start, uint32 stop) { +static __always_inline void dispatch_extis(uint32 start, uint32 stop) { uint32 pr = EXTI_BASE->PR; uint32 handled_msk = 0; uint32 exti; /* Dispatch user handlers for pending EXTIs. */ for (exti = start; exti <= stop; exti++) { - uint32 eb = BIT(exti); + uint32 eb = (1U << exti); if (pr & eb) { voidFuncPtr handler = exti_channels[exti].handler; if (handler) { diff --git a/libmaple/exti_private.h b/libmaple/exti_private.h new file mode 100644 index 0000000..4f0a4cf --- /dev/null +++ b/libmaple/exti_private.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * 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. +*****************************************************************************/ + +#ifndef _LIBMAPLE_EXTI_PRIVATE_H_ +#define _LIBMAPLE_EXTI_PRIVATE_H_ + +#include + +void exti_do_select(__io uint32 *exti_cr, exti_num num, exti_cfg port); + +#endif diff --git a/libmaple/include/libmaple/exti.h b/libmaple/include/libmaple/exti.h index d7bfe51..5259a44 100644 --- a/libmaple/include/libmaple/exti.h +++ b/libmaple/include/libmaple/exti.h @@ -26,7 +26,7 @@ /** * @file libmaple/include/libmaple/exti.h - * @brief External interrupt control prototypes and defines + * @brief External interrupt control */ /* See notes/exti.txt for more info */ @@ -38,8 +38,11 @@ extern "C"{ #endif -#include -#include +#include + +/* + * Register map and base pointer. + */ /** EXTI register map type */ typedef struct exti_reg_map { @@ -54,6 +57,51 @@ typedef struct exti_reg_map { /** EXTI register map base pointer */ #define EXTI_BASE ((struct exti_reg_map*)0x40010400) +/* + * Types: exti_num, exti_cfg, exti_trigger_mode. + * + * A combination of these three specifies an external interrupt + * configuration (see exti_attach_interrupt()). + */ + +/** EXTI line. */ +typedef enum exti_num { + EXTI0, /**< EXTI line 0 */ + EXTI1, /**< EXTI line 1 */ + EXTI2, /**< EXTI line 2 */ + EXTI3, /**< EXTI line 3 */ + EXTI4, /**< EXTI line 4 */ + EXTI5, /**< EXTI line 5 */ + EXTI6, /**< EXTI line 6 */ + EXTI7, /**< EXTI line 7 */ + EXTI8, /**< EXTI line 8 */ + EXTI9, /**< EXTI line 9 */ + EXTI10, /**< EXTI line 10 */ + EXTI11, /**< EXTI line 11 */ + EXTI12, /**< EXTI line 12 */ + EXTI13, /**< EXTI line 13 */ + EXTI14, /**< EXTI line 14 */ + EXTI15, /**< EXTI line 15 */ +} exti_num; + +/** + * @brief EXTI port configuration + * + * These specify which GPIO port an external interrupt line should be + * connected to. + */ +typedef enum exti_cfg { + EXTI_PA, /**< Use PAx pin */ + EXTI_PB, /**< Use PBx pin */ + EXTI_PC, /**< Use PCx pin */ + EXTI_PD, /**< Use PDx pin */ + EXTI_PE, /**< Use PEx pin */ + EXTI_PF, /**< Use PFx pin */ + EXTI_PG, /**< Use PGx pin */ + EXTI_PH, /**< Use PHx pin */ + EXTI_PI, /**< Use PIx pin */ +} exti_cfg; + /** External interrupt trigger mode */ typedef enum exti_trigger_mode { EXTI_RISING, /**< Trigger on the rising edge */ @@ -61,11 +109,29 @@ typedef enum exti_trigger_mode { EXTI_RISING_FALLING /**< Trigger on both the rising and falling edges */ } exti_trigger_mode; -void exti_attach_interrupt(afio_exti_num num, - afio_exti_port port, +/* + * Routines + */ + +void exti_attach_interrupt(exti_num num, + exti_cfg port, voidFuncPtr handler, exti_trigger_mode mode); -void exti_detach_interrupt(afio_exti_num num); +void exti_detach_interrupt(exti_num num); + +/** + * @brief Set the GPIO port for an EXTI line. + * + * This is a low-level routine that most users will not + * need. exti_attach_interrupt() handles calling this function + * appropriately. + * + * @param num EXTI line + * @param port EXTI configuration for GPIO port to connect to num. + * @see exti_num + * @see exti_cfg + */ +extern void exti_select(exti_num num, exti_cfg port); #ifdef __cplusplus } // extern "C" diff --git a/libmaple/include/libmaple/gpio.h b/libmaple/include/libmaple/gpio.h index ca7b2bf..0cc3746 100644 --- a/libmaple/include/libmaple/gpio.h +++ b/libmaple/include/libmaple/gpio.h @@ -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 @@ -38,21 +39,45 @@ extern "C"{ /* * Note: Series header must define: - * - struct gpio_dev (and declare extern pointers to series-provided ones) - * - enum gpio_pin_mode (TODO think hard on this) + * - enum gpio_pin_mode (TODO think harder about portability here) */ #include -#include +#include +#include +#include /* - * GPIO Convenience routines + * Device type + */ + +/** GPIO device type */ +typedef struct gpio_dev { + gpio_reg_map *regs; /**< Register map */ + rcc_clk_id clk_id; /**< RCC clock information */ + /** + * @brief (Deprecated) External interrupt port. + * Instead of dev->exti_port, use gpio_exti_port(dev). + */ + exti_cfg exti_port; +} gpio_dev; + +/* + * Portable routines */ void gpio_init(gpio_dev *dev); void gpio_init_all(void); -/* TODO deprecate this? We should probably take a flags argument. */ +/* TODO flags argument version? */ void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode); +/** + * @brief Get a GPIO port's corresponding EXTI port configuration. + * @param dev GPIO port whose exti_cfg to return. + */ +static inline exti_cfg gpio_exti_port(gpio_dev *dev) { + return (exti_cfg)(EXTI_PA + (dev->clk_id - RCC_GPIOA)); +} + /** * Set or reset a GPIO pin. * @@ -64,7 +89,7 @@ void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode); */ static inline void gpio_write_bit(gpio_dev *dev, uint8 pin, uint8 val) { val = !val; /* "set" bits are lower than "reset" bits */ - dev->regs->BSRR = BIT(pin) << (16 * val); + dev->regs->BSRR = (1U << pin) << (16 * val); } /** @@ -77,7 +102,7 @@ static inline void gpio_write_bit(gpio_dev *dev, uint8 pin, uint8 val) { * @return True if the pin is set, false otherwise. */ static inline uint32 gpio_read_bit(gpio_dev *dev, uint8 pin) { - return dev->regs->IDR & BIT(pin); + return dev->regs->IDR & (1U << pin); } /** @@ -86,7 +111,7 @@ static inline uint32 gpio_read_bit(gpio_dev *dev, uint8 pin) { * @param pin Pin on dev to toggle. */ static inline void gpio_toggle_bit(gpio_dev *dev, uint8 pin) { - dev->regs->ODR = dev->regs->ODR ^ BIT(pin); + dev->regs->ODR = dev->regs->ODR ^ (1U << pin); } #ifdef __cplusplus diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 5c63522..b39c318 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -13,6 +13,7 @@ CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets cSRCS_$(d) := adc.c # cSRCS_$(d) += dma.c +cSRCS_$(d) += exti.c cSRCS_$(d) += flash.c cSRCS_$(d) += gpio.c cSRCS_$(d) += iwdg.c @@ -28,7 +29,6 @@ cSRCS_$(d) += usart_private.c cSRCS_$(d) += util.c # These still need to be brought back for F1: # cSRCS_$(d) += dac.c -# cSRCS_$(d) += exti.c # cSRCS_$(d) += i2c.c sSRCS_$(d) := exc.S diff --git a/libmaple/stm32f1/exti.c b/libmaple/stm32f1/exti.c new file mode 100644 index 0000000..b9ff401 --- /dev/null +++ b/libmaple/stm32f1/exti.c @@ -0,0 +1,32 @@ +/****************************************************************************** + * 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. +*****************************************************************************/ + +#include +#include "exti_private.h" + +void exti_select(exti_num num, exti_cfg port) { + exti_do_select(&AFIO_BASE->EXTICR1 + num / 4, num, port); +} diff --git a/libmaple/stm32f1/gpio.c b/libmaple/stm32f1/gpio.c index 2cbe299..4b596e9 100644 --- a/libmaple/stm32f1/gpio.c +++ b/libmaple/stm32f1/gpio.c @@ -39,7 +39,7 @@ gpio_dev gpioa = { .regs = GPIOA_BASE, .clk_id = RCC_GPIOA, - .exti_port = AFIO_EXTI_PA, + .exti_port = EXTI_PA, }; /** GPIO port A device. */ gpio_dev* const GPIOA = &gpioa; @@ -47,7 +47,7 @@ gpio_dev* const GPIOA = &gpioa; gpio_dev gpiob = { .regs = GPIOB_BASE, .clk_id = RCC_GPIOB, - .exti_port = AFIO_EXTI_PB, + .exti_port = EXTI_PB, }; /** GPIO port B device. */ gpio_dev* const GPIOB = &gpiob; @@ -55,7 +55,7 @@ gpio_dev* const GPIOB = &gpiob; gpio_dev gpioc = { .regs = GPIOC_BASE, .clk_id = RCC_GPIOC, - .exti_port = AFIO_EXTI_PC, + .exti_port = EXTI_PC, }; /** GPIO port C device. */ gpio_dev* const GPIOC = &gpioc; @@ -63,7 +63,7 @@ gpio_dev* const GPIOC = &gpioc; gpio_dev gpiod = { .regs = GPIOD_BASE, .clk_id = RCC_GPIOD, - .exti_port = AFIO_EXTI_PD, + .exti_port = EXTI_PD, }; /** GPIO port D device. */ gpio_dev* const GPIOD = &gpiod; @@ -72,7 +72,7 @@ gpio_dev* const GPIOD = &gpiod; gpio_dev gpioe = { .regs = GPIOE_BASE, .clk_id = RCC_GPIOE, - .exti_port = AFIO_EXTI_PE, + .exti_port = EXTI_PE, }; /** GPIO port E device. */ gpio_dev* const GPIOE = &gpioe; @@ -80,7 +80,7 @@ gpio_dev* const GPIOE = &gpioe; gpio_dev gpiof = { .regs = GPIOF_BASE, .clk_id = RCC_GPIOF, - .exti_port = AFIO_EXTI_PF, + .exti_port = EXTI_PF, }; /** GPIO port F device. */ gpio_dev* const GPIOF = &gpiof; @@ -88,7 +88,7 @@ gpio_dev* const GPIOF = &gpiof; gpio_dev gpiog = { .regs = GPIOG_BASE, .clk_id = RCC_GPIOG, - .exti_port = AFIO_EXTI_PG, + .exti_port = EXTI_PG, }; /** GPIO port G device. */ gpio_dev* const GPIOG = &gpiog; @@ -132,9 +132,9 @@ void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode) { *cr = tmp; if (mode == GPIO_INPUT_PD) { - regs->ODR &= ~BIT(pin); + regs->ODR &= ~(1U << pin); } else if (mode == GPIO_INPUT_PU) { - regs->ODR |= BIT(pin); + regs->ODR |= (1U << pin); } } @@ -152,24 +152,6 @@ void afio_init(void) { #define AFIO_EXTI_SEL_MASK 0xF -/** - * @brief Select a source input for an external interrupt. - * - * @param exti External interrupt. - * @param gpio_port Port which contains pin to use as source input. - * @see afio_exti_num - * @see afio_exti_port - */ -void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port) { - __io uint32 *exti_cr = &AFIO_BASE->EXTICR1 + exti / 4; - uint32 shift = 4 * (exti % 4); - uint32 cr = *exti_cr; - - cr &= ~(AFIO_EXTI_SEL_MASK << shift); - cr |= gpio_port << shift; - *exti_cr = cr; -} - /** * @brief Perform an alternate function remap. * @param remapping Remapping to perform. diff --git a/libmaple/stm32f1/include/series/gpio.h b/libmaple/stm32f1/include/series/gpio.h index 1f209fe..0ca6d56 100644 --- a/libmaple/stm32f1/include/series/gpio.h +++ b/libmaple/stm32f1/include/series/gpio.h @@ -2,7 +2,7 @@ * The MIT License * * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011 LeafLabs, LLC. + * 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 @@ -27,7 +27,7 @@ /** * @file libmaple/stm32f1/include/series/gpio.h - * @brief STM32F1 GPIO support. + * @brief STM32F1 GPIO and AFIO support. * * General purpose I/O (GPIO) and Alternate Function I/O (AFIO) * prototypes, defines, and support functions. @@ -40,8 +40,9 @@ extern "C"{ #endif -#include -#include +#include +#include +#include /* * GPIO register maps and devices @@ -58,46 +59,22 @@ typedef struct gpio_reg_map { __io uint32 LCKR; /**< Port configuration lock register */ } gpio_reg_map; -/** - * @brief External interrupt line port selector. - * - * Used to determine which GPIO port to map an external interrupt line - * onto. */ -/* (See AFIO sections, below) */ -typedef enum afio_exti_port { - AFIO_EXTI_PA, /**< Use port A (PAx) pin. */ - AFIO_EXTI_PB, /**< Use port B (PBx) pin. */ - AFIO_EXTI_PC, /**< Use port C (PCx) pin. */ - AFIO_EXTI_PD, /**< Use port D (PDx) pin. */ -#ifdef STM32_HIGH_DENSITY - AFIO_EXTI_PE, /**< Use port E (PEx) pin. */ - AFIO_EXTI_PF, /**< Use port F (PFx) pin. */ - AFIO_EXTI_PG, /**< Use port G (PGx) pin. */ -#endif -} afio_exti_port; - -/** GPIO device type */ -typedef struct gpio_dev { - gpio_reg_map *regs; /**< Register map */ - rcc_clk_id clk_id; /**< RCC clock information */ - afio_exti_port exti_port; /**< AFIO external interrupt port value */ -} gpio_dev; - -extern gpio_dev gpioa; -extern gpio_dev* const GPIOA; -extern gpio_dev gpiob; -extern gpio_dev* const GPIOB; -extern gpio_dev gpioc; -extern gpio_dev* const GPIOC; -extern gpio_dev gpiod; -extern gpio_dev* const GPIOD; +struct gpio_dev; +extern struct gpio_dev gpioa; +extern struct gpio_dev* const GPIOA; +extern struct gpio_dev gpiob; +extern struct gpio_dev* const GPIOB; +extern struct gpio_dev gpioc; +extern struct gpio_dev* const GPIOC; +extern struct gpio_dev gpiod; +extern struct gpio_dev* const GPIOD; #ifdef STM32_HIGH_DENSITY -extern gpio_dev gpioe; -extern gpio_dev* const GPIOE; -extern gpio_dev gpiof; -extern gpio_dev* const GPIOF; -extern gpio_dev gpiog; -extern gpio_dev* const GPIOG; +extern struct gpio_dev gpioe; +extern struct gpio_dev* const GPIOE; +extern struct gpio_dev gpiof; +extern struct gpio_dev* const GPIOF; +extern struct gpio_dev gpiog; +extern struct gpio_dev* const GPIOG; #endif /** GPIO port A register map base pointer */ @@ -108,14 +85,12 @@ extern gpio_dev* const GPIOG; #define GPIOC_BASE ((struct gpio_reg_map*)0x40011000) /** GPIO port D register map base pointer */ #define GPIOD_BASE ((struct gpio_reg_map*)0x40011400) -#ifdef STM32_HIGH_DENSITY /** GPIO port E register map base pointer */ #define GPIOE_BASE ((struct gpio_reg_map*)0x40011800) /** GPIO port F register map base pointer */ #define GPIOF_BASE ((struct gpio_reg_map*)0x40011C00) /** GPIO port G register map base pointer */ #define GPIOG_BASE ((struct gpio_reg_map*)0x40012000) -#endif /* * GPIO register bit definitions @@ -138,7 +113,7 @@ extern gpio_dev* const GPIOG; #define GPIO_CR_MODE_OUTPUT_50MHZ 0x3 /** - * @brief GPIO Pin modes. + * @brief GPIO pin modes. * * These only allow for 50MHZ max output speeds; if you want slower, * use direct register access. @@ -164,14 +139,6 @@ typedef enum gpio_pin_mode { /* GPIO_INPUT_PU treated as a special case, for ODR twiddling */ } gpio_pin_mode; -/** - * @brief Get a GPIO port's corresponding afio_exti_port. - * @param dev GPIO device whose afio_exti_port to return. - */ -static inline afio_exti_port gpio_exti_port(gpio_dev *dev) { - return dev->exti_port; -} - /* * AFIO register map */ @@ -232,17 +199,17 @@ typedef struct afio_reg_map { #define AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST (0x1 << 24) #define AFIO_MAPR_SWJ_CFG_NO_JTAG_SW (0x2 << 24) #define AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW (0x4 << 24) -#define AFIO_MAPR_ADC2_ETRGREG_REMAP BIT(20) -#define AFIO_MAPR_ADC2_ETRGINJ_REMAP BIT(19) -#define AFIO_MAPR_ADC1_ETRGREG_REMAP BIT(18) -#define AFIO_MAPR_ADC1_ETRGINJ_REMAP BIT(17) -#define AFIO_MAPR_TIM5CH4_IREMAP BIT(16) -#define AFIO_MAPR_PD01_REMAP BIT(15) +#define AFIO_MAPR_ADC2_ETRGREG_REMAP (1U << 20) +#define AFIO_MAPR_ADC2_ETRGINJ_REMAP (1U << 19) +#define AFIO_MAPR_ADC1_ETRGREG_REMAP (1U << 18) +#define AFIO_MAPR_ADC1_ETRGINJ_REMAP (1U << 17) +#define AFIO_MAPR_TIM5CH4_IREMAP (1U << 16) +#define AFIO_MAPR_PD01_REMAP (1U << 15) #define AFIO_MAPR_CAN_REMAP (0x3 << 13) #define AFIO_MAPR_CAN_REMAP_NONE (0x0 << 13) #define AFIO_MAPR_CAN_REMAP_PB8_PB9 (0x2 << 13) #define AFIO_MAPR_CAN_REMAP_PD0_PD1 (0x3 << 13) -#define AFIO_MAPR_TIM4_REMAP BIT(12) +#define AFIO_MAPR_TIM4_REMAP (1U << 12) #define AFIO_MAPR_TIM3_REMAP (0x3 << 10) #define AFIO_MAPR_TIM3_REMAP_NONE (0x0 << 10) #define AFIO_MAPR_TIM3_REMAP_PARTIAL (0x2 << 10) @@ -260,10 +227,10 @@ typedef struct afio_reg_map { #define AFIO_MAPR_USART3_REMAP_NONE (0x0 << 4) #define AFIO_MAPR_USART3_REMAP_PARTIAL (0x1 << 4) #define AFIO_MAPR_USART3_REMAP_FULL (0x3 << 4) -#define AFIO_MAPR_USART2_REMAP BIT(3) -#define AFIO_MAPR_USART1_REMAP BIT(2) -#define AFIO_MAPR_I2C1_REMAP BIT(1) -#define AFIO_MAPR_SPI1_REMAP BIT(0) +#define AFIO_MAPR_USART2_REMAP (1U << 3) +#define AFIO_MAPR_USART1_REMAP (1U << 2) +#define AFIO_MAPR_I2C1_REMAP (1U << 1) +#define AFIO_MAPR_SPI1_REMAP (1U << 0) /* External interrupt configuration register 1 */ @@ -337,12 +304,12 @@ typedef struct afio_reg_map { /* AF remap and debug I/O configuration register 2 */ -#define AFIO_MAPR2_FSMC_NADV BIT(10) -#define AFIO_MAPR2_TIM14_REMAP BIT(9) -#define AFIO_MAPR2_TIM13_REMAP BIT(8) -#define AFIO_MAPR2_TIM11_REMAP BIT(7) -#define AFIO_MAPR2_TIM10_REMAP BIT(6) -#define AFIO_MAPR2_TIM9_REMAP BIT(5) +#define AFIO_MAPR2_FSMC_NADV (1U << 10) +#define AFIO_MAPR2_TIM14_REMAP (1U << 9) +#define AFIO_MAPR2_TIM13_REMAP (1U << 8) +#define AFIO_MAPR2_TIM11_REMAP (1U << 7) +#define AFIO_MAPR2_TIM10_REMAP (1U << 6) +#define AFIO_MAPR2_TIM9_REMAP (1U << 5) /* * AFIO convenience routines @@ -350,33 +317,9 @@ typedef struct afio_reg_map { void afio_init(void); -/** - * External interrupt line numbers. - */ -typedef enum afio_exti_num { - AFIO_EXTI_0, /**< External interrupt line 0. */ - AFIO_EXTI_1, /**< External interrupt line 1. */ - AFIO_EXTI_2, /**< External interrupt line 2. */ - AFIO_EXTI_3, /**< External interrupt line 3. */ - AFIO_EXTI_4, /**< External interrupt line 4. */ - AFIO_EXTI_5, /**< External interrupt line 5. */ - AFIO_EXTI_6, /**< External interrupt line 6. */ - AFIO_EXTI_7, /**< External interrupt line 7. */ - AFIO_EXTI_8, /**< External interrupt line 8. */ - AFIO_EXTI_9, /**< External interrupt line 9. */ - AFIO_EXTI_10, /**< External interrupt line 10. */ - AFIO_EXTI_11, /**< External interrupt line 11. */ - AFIO_EXTI_12, /**< External interrupt line 12. */ - AFIO_EXTI_13, /**< External interrupt line 13. */ - AFIO_EXTI_14, /**< External interrupt line 14. */ - AFIO_EXTI_15, /**< External interrupt line 15. */ -} afio_exti_num; - -void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port); - /* HACK: Use upper bit to denote MAPR2, Bit 31 is reserved and * not used in either MAPR or MAPR2 */ -#define AFIO_REMAP_USE_MAPR2 (1 << 31) +#define AFIO_REMAP_USE_MAPR2 (1U << 31) /** * @brief Available peripheral remaps. @@ -474,6 +417,86 @@ static inline void afio_cfg_debug_ports(afio_debug_cfg config) { *mapr = (*mapr & ~AFIO_MAPR_SWJ_CFG) | config; } +/* + * Deprecated bits + */ + +/** + * @brief Deprecated. Use exti_cfg instead. + * + * In previous versions of libmaple, exti_attach_interrupt() took an + * afio_exti_port argument; afio_exti_port was also a member of struct + * gpio_dev. This isn't portable, so we now use exti_cfg + * instead. This typedef (and the macros AFIO_EXTI_PA, ..., + * AFIO_EXTI_PG) exist to preserve backwards compatibility. + */ +typedef exti_cfg afio_exti_port; + +/** Deprecated. Use EXTI_PA instead. */ +#define AFIO_EXTI_PA EXTI_PA +/** Deprecated. Use EXTI_PB instead. */ +#define AFIO_EXTI_PB EXTI_PB +/** Deprecated. Use EXTI_PC instead. */ +#define AFIO_EXTI_PC EXTI_PC +/** Deprecated. Use EXTI_PD instead. */ +#define AFIO_EXTI_PD EXTI_PD +/** Deprecated. Use EXTI_PE instead. */ +#define AFIO_EXTI_PE EXTI_PE +/** Deprecated. Use EXTI_PF instead. */ +#define AFIO_EXTI_PF EXTI_PF +/** Deprecated. Use EXTI_PG instead. */ +#define AFIO_EXTI_PG EXTI_PG + +/** + * @brief Deprecated. Use exti_num instead. + * + * In previous versions of libmaple, exti_attach_interrupt() took an + * afio_exti_num argument. This isn't portable, so we use exti_num + * instead. This typedef (and the macros AFIO_EXTI_0, ..., + * AFIO_EXTI_15) exist to preserve backwards compatibility. + */ +typedef exti_num afio_exti_num; + +/** Deprecated. Use EXTI0 instead. */ +#define AFIO_EXTI_0 EXTI0 +/** Deprecated. Use EXTI1 instead. */ +#define AFIO_EXTI_1 EXTI1 +/** Deprecated. Use EXTI2 instead. */ +#define AFIO_EXTI_2 EXTI2 +/** Deprecated. Use EXTI3 instead. */ +#define AFIO_EXTI_3 EXTI3 +/** Deprecated. Use EXTI4 instead. */ +#define AFIO_EXTI_4 EXTI4 +/** Deprecated. Use EXTI5 instead. */ +#define AFIO_EXTI_5 EXTI5 +/** Deprecated. Use EXTI6 instead. */ +#define AFIO_EXTI_6 EXTI6 +/** Deprecated. Use EXTI7 instead. */ +#define AFIO_EXTI_7 EXTI7 +/** Deprecated. Use EXTI8 instead. */ +#define AFIO_EXTI_8 EXTI8 +/** Deprecated. Use EXTI9 instead. */ +#define AFIO_EXTI_9 EXTI9 +/** Deprecated. Use EXTI10 instead. */ +#define AFIO_EXTI_10 EXTI10 +/** Deprecated. Use EXTI11 instead. */ +#define AFIO_EXTI_11 EXTI11 +/** Deprecated. Use EXTI12 instead. */ +#define AFIO_EXTI_12 EXTI12 +/** Deprecated. Use EXTI13 instead. */ +#define AFIO_EXTI_13 EXTI13 +/** Deprecated. Use EXTI14 instead. */ +#define AFIO_EXTI_14 EXTI14 +/** Deprecated. Use EXTI15 instead. */ +#define AFIO_EXTI_15 EXTI15 + +/** + * @brief Deprecated. Use exti_select(exti, port) instead. + */ +static __always_inline void afio_exti_select(exti_num exti, exti_cfg port) { + exti_select(exti, port); +} + #ifdef __cplusplus } #endif diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk index 0effea3..15f6fdb 100644 --- a/libmaple/stm32f1/rules.mk +++ b/libmaple/stm32f1/rules.mk @@ -17,6 +17,7 @@ sSRCS_$(d) += $(MCU_F1_LINE)/vector_table.S cSRCS_$(d) := adc.c cSRCS_$(d) += bkp.c cSRCS_$(d) += dma.c +cSRCS_$(d) += exti.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c cSRCS_$(d) += rcc.c diff --git a/libmaple/stm32f2/gpio.c b/libmaple/stm32f2/gpio.c index f2cd776..a26edaa 100644 --- a/libmaple/stm32f2/gpio.c +++ b/libmaple/stm32f2/gpio.c @@ -40,6 +40,7 @@ gpio_dev gpioa = { .regs = GPIOA_BASE, .clk_id = RCC_GPIOA, + .exti_port = EXTI_PA, }; /** GPIO port A device. */ gpio_dev* const GPIOA = &gpioa; @@ -47,6 +48,7 @@ gpio_dev* const GPIOA = &gpioa; gpio_dev gpiob = { .regs = GPIOB_BASE, .clk_id = RCC_GPIOB, + .exti_port = EXTI_PB, }; /** GPIO port B device. */ gpio_dev* const GPIOB = &gpiob; @@ -54,6 +56,7 @@ gpio_dev* const GPIOB = &gpiob; gpio_dev gpioc = { .regs = GPIOC_BASE, .clk_id = RCC_GPIOC, + .exti_port = EXTI_PC, }; /** GPIO port C device. */ gpio_dev* const GPIOC = &gpioc; @@ -61,6 +64,7 @@ gpio_dev* const GPIOC = &gpioc; gpio_dev gpiod = { .regs = GPIOD_BASE, .clk_id = RCC_GPIOD, + .exti_port = EXTI_PD, }; /** GPIO port D device. */ gpio_dev* const GPIOD = &gpiod; @@ -68,6 +72,7 @@ gpio_dev* const GPIOD = &gpiod; gpio_dev gpioe = { .regs = GPIOE_BASE, .clk_id = RCC_GPIOE, + .exti_port = EXTI_PE, }; /** GPIO port E device. */ gpio_dev* const GPIOE = &gpioe; @@ -75,6 +80,7 @@ gpio_dev* const GPIOE = &gpioe; gpio_dev gpiof = { .regs = GPIOF_BASE, .clk_id = RCC_GPIOF, + .exti_port = EXTI_PF, }; /** GPIO port F device. */ gpio_dev* const GPIOF = &gpiof; @@ -82,6 +88,7 @@ gpio_dev* const GPIOF = &gpiof; gpio_dev gpiog = { .regs = GPIOG_BASE, .clk_id = RCC_GPIOG, + .exti_port = EXTI_PG, }; /** GPIO port G device. */ gpio_dev* const GPIOG = &gpiog; @@ -89,6 +96,7 @@ gpio_dev* const GPIOG = &gpiog; gpio_dev gpioh = { .regs = GPIOH_BASE, .clk_id = RCC_GPIOH, + .exti_port = EXTI_PH, }; /** GPIO port G device. */ gpio_dev* const GPIOH = &gpioh; @@ -96,6 +104,7 @@ gpio_dev* const GPIOH = &gpioh; gpio_dev gpioi = { .regs = GPIOI_BASE, .clk_id = RCC_GPIOI, + .exti_port = EXTI_PI, }; /** GPIO port G device. */ gpio_dev* const GPIOI = &gpioi; diff --git a/libmaple/stm32f2/include/series/gpio.h b/libmaple/stm32f2/include/series/gpio.h index 9687247..1496e8e 100644 --- a/libmaple/stm32f2/include/series/gpio.h +++ b/libmaple/stm32f2/include/series/gpio.h @@ -1,7 +1,7 @@ /****************************************************************************** * The MIT License * - * Copyright (c) 2011 LeafLabs, LLC. + * 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 @@ -36,8 +36,7 @@ extern "C"{ #endif -#include -#include +#include /* * GPIO register maps and devices @@ -76,30 +75,25 @@ typedef struct gpio_reg_map { /** GPIO port I register map base pointer */ #define GPIOI_BASE ((struct gpio_reg_map*)0x40022000) -/** GPIO device type */ -typedef struct gpio_dev { - gpio_reg_map *regs; - rcc_clk_id clk_id; -} gpio_dev; - -extern gpio_dev* const GPIOA; -extern gpio_dev gpioa; -extern gpio_dev* const GPIOB; -extern gpio_dev gpiob; -extern gpio_dev* const GPIOC; -extern gpio_dev gpioc; -extern gpio_dev* const GPIOD; -extern gpio_dev gpiod; -extern gpio_dev* const GPIOE; -extern gpio_dev gpioe; -extern gpio_dev* const GPIOF; -extern gpio_dev gpiof; -extern gpio_dev* const GPIOG; -extern gpio_dev gpiog; -extern gpio_dev* const GPIOH; -extern gpio_dev gpioh; -extern gpio_dev* const GPIOI; -extern gpio_dev gpioi; +struct gpio_dev; +extern struct gpio_dev* const GPIOA; +extern struct gpio_dev gpioa; +extern struct gpio_dev* const GPIOB; +extern struct gpio_dev gpiob; +extern struct gpio_dev* const GPIOC; +extern struct gpio_dev gpioc; +extern struct gpio_dev* const GPIOD; +extern struct gpio_dev gpiod; +extern struct gpio_dev* const GPIOE; +extern struct gpio_dev gpioe; +extern struct gpio_dev* const GPIOF; +extern struct gpio_dev gpiof; +extern struct gpio_dev* const GPIOG; +extern struct gpio_dev gpiog; +extern struct gpio_dev* const GPIOH; +extern struct gpio_dev gpioh; +extern struct gpio_dev* const GPIOI; +extern struct gpio_dev gpioi; /* * Register bit definitions @@ -215,7 +209,7 @@ typedef enum gpio_mode_flags { GPIO_MODEF_PUPD_PD = GPIO_PUPDR_PD << 3, /**< Pull-down */ } gpio_mode_flags; -void gpio_set_modef(gpio_dev *dev, +void gpio_set_modef(struct gpio_dev *dev, uint8 bit, gpio_pin_mode mode, unsigned flags); @@ -231,7 +225,7 @@ void gpio_set_modef(gpio_dev *dev, * @param pin Pin on the device whose mode to set, 0--15. * @param mode Mode to set the pin to. */ -static inline void gpio_set_mode(gpio_dev *dev, +static inline void gpio_set_mode(struct gpio_dev *dev, uint8 bit, gpio_pin_mode mode) { gpio_set_modef(dev, bit, mode, GPIO_MODEF_SPEED_HIGH); @@ -261,7 +255,7 @@ typedef enum gpio_af { GPIO_AF_EVENTOUT = 15, /**< EVENTOUT. */ } gpio_af; -void gpio_set_af(gpio_dev *dev, uint8 bit, gpio_af af); +void gpio_set_af(struct gpio_dev *dev, uint8 bit, gpio_af af); #ifdef __cplusplus } -- cgit v1.2.3