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/include/libmaple/exti.h | 78 ++++++++++++++++++++++++++++++++++++---- libmaple/include/libmaple/gpio.h | 41 ++++++++++++++++----- 2 files changed, 105 insertions(+), 14 deletions(-) (limited to 'libmaple/include') 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 -- cgit v1.2.3