aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HACKING_COMMON_DOC62
-rw-r--r--include/libopencm3/stm32/common/gpio_common_all.h73
-rw-r--r--include/libopencm3/stm32/common/gpio_common_f24.h285
-rw-r--r--include/libopencm3/stm32/gpio.h29
-rw-r--r--lib/stm32/common/gpio_common_all.c139
-rw-r--r--lib/stm32/common/gpio_common_f24.c195
6 files changed, 783 insertions, 0 deletions
diff --git a/HACKING_COMMON_DOC b/HACKING_COMMON_DOC
new file mode 100644
index 0000000..fa78271
--- /dev/null
+++ b/HACKING_COMMON_DOC
@@ -0,0 +1,62 @@
+Files for each peripheral (examples given for STM32 GPIO)
+---------------------------------------------------------
+
+In include/libopencm3/stm32.
+A "dispatch" header to point to the subfamily header (gpio.h)
+
+In include/libopencm3/stm32/f*
+A file with defines that are specific to the subfamily, and an include of
+needed common header files (gpio.h).
+
+In include/libopencm3/stm32/common
+A file with defines common to all subfamilies. Includes the cm3 common header
+(gpio_common_all.h).
+
+In include/libopencm3/stm32/common
+May be one other file with defines common to a subgroup of devices.
+This includes the file common to all (gpio_common_f24.h).
+
+In lib/stm32/f*
+A file with functions specific to the subfamily. Includes the "dispatch" header
+and any common headers needed (gpio.c).
+
+In lib/stm32/common
+Has functions common to all subfamilies. Includes the "dispatch" header
+(gpio_common_all.c).
+
+In lib/stm32/common
+May be one other file with functions common to a group of subfamilies. Includes
+the "dispatch" header and the file common to all (gpio_common_f24.h).
+
+Makefiles in lib/stm32/f? have the common object files added and the
+common directory added to VPATH.
+
+NOTE: The common source files MUST have the "dispatch" header so that
+compilation will use the specific defines for the subfamily being compiled.
+These can differ between subfamilies.
+
+Documentation
+-------------
+
+In include/libopencm3/stm32/f*
+A file doc-stm32f*.h contains a definition of the particular family grouping.
+This grouping will appear in the main index of the resulting document with all
+documentation under it.
+
+All header files for a peripheral (common or otherwise) will subgroup under a
+name which is the same in all families (such as gpio_defines). The peripheral
+header file in include/libopencm3/stm32/f* will then include this group as a
+subgroup under the specific family group. Doxygen is run separately for each
+family so there is no danger of accidentally including the wrong stuff.
+
+Similarly for the source files for a peripheral which will subgroup under a
+same name (such as gpio_files). The peripheral source file in lib/stm32/f*
+will include this as a subgroup under the specific family group.
+
+DOXYFILE for a particular family will list the family specific and common files
+(headers and source) that are to be included. The result (in the long run) will
+be that all peripherals will appear under the same family grouping in the
+documentation, even if they are identical over a number of families. That is
+probably most useful to end users who only need to see the documentation for
+one family.
+
diff --git a/include/libopencm3/stm32/common/gpio_common_all.h b/include/libopencm3/stm32/common/gpio_common_all.h
new file mode 100644
index 0000000..b2327e5
--- /dev/null
+++ b/include/libopencm3/stm32/common/gpio_common_all.h
@@ -0,0 +1,73 @@
+/** @addtogroup gpio_defines */
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
+ * Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY, BUT ONLY VIA GPIO.H */
+
+#ifndef LIBOPENCM3_GPIO_COMMON_ALL_H
+#define LIBOPENCM3_GPIO_COMMON_ALL_H
+
+/**@{*/
+
+#include <libopencm3/cm3/common.h>
+
+/* --- Convenience macros -------------------------------------------------- */
+
+/* --- GPIO_LCKR values ---------------------------------------------------- */
+
+#define GPIO_LCKK (1 << 16)
+/* GPIO_LCKR[15:0]: LCKy: Port x lock bit y (y = 0..15) */
+
+/* GPIO number definitions (for convenience) */
+/** @defgroup gpio_pin_id GPIO Pin Identifiers
+@ingroup gpio_defines
+
+@{*/
+#define GPIO0 (1 << 0)
+#define GPIO1 (1 << 1)
+#define GPIO2 (1 << 2)
+#define GPIO3 (1 << 3)
+#define GPIO4 (1 << 4)
+#define GPIO5 (1 << 5)
+#define GPIO6 (1 << 6)
+#define GPIO7 (1 << 7)
+#define GPIO8 (1 << 8)
+#define GPIO9 (1 << 9)
+#define GPIO10 (1 << 10)
+#define GPIO11 (1 << 11)
+#define GPIO12 (1 << 12)
+#define GPIO13 (1 << 13)
+#define GPIO14 (1 << 14)
+#define GPIO15 (1 << 15)
+#define GPIO_ALL 0xffff
+/**@}*/
+
+void gpio_set(u32 gpioport, u16 gpios);
+void gpio_clear(u32 gpioport, u16 gpios);
+u16 gpio_get(u32 gpioport, u16 gpios);
+void gpio_toggle(u32 gpioport, u16 gpios);
+u16 gpio_port_read(u32 gpioport);
+void gpio_port_write(u32 gpioport, u16 data);
+void gpio_port_config_lock(u32 gpioport, u16 gpios);
+
+/**@}*/
+#endif
+
diff --git a/include/libopencm3/stm32/common/gpio_common_f24.h b/include/libopencm3/stm32/common/gpio_common_f24.h
new file mode 100644
index 0000000..f8bd4fb
--- /dev/null
+++ b/include/libopencm3/stm32/common/gpio_common_f24.h
@@ -0,0 +1,285 @@
+/** @addtogroup gpio_defines */
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
+ * Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY, BUT ONLY VIA GPIO.H */
+
+#ifndef LIBOPENCM3_GPIO_COMMON_F24_H
+#define LIBOPENCM3_GPIO_COMMON_F24_H
+
+/**@{*/
+
+#include <libopencm3/stm32/common/gpio_common_all.h>
+
+/* GPIO port base addresses (for convenience) */
+/** @defgroup gpio_port_id GPIO Port IDs
+@ingroup gpio_defines
+
+@{*/
+#define GPIOA GPIO_PORT_A_BASE
+#define GPIOB GPIO_PORT_B_BASE
+#define GPIOC GPIO_PORT_C_BASE
+#define GPIOD GPIO_PORT_D_BASE
+#define GPIOE GPIO_PORT_E_BASE
+#define GPIOF GPIO_PORT_F_BASE
+#define GPIOG GPIO_PORT_G_BASE
+#define GPIOH GPIO_PORT_H_BASE
+#define GPIOI GPIO_PORT_I_BASE
+/**@}*/
+
+/* --- GPIO registers for STM32F2 and STM32F4 --------------------------- */
+
+/* Port mode register (GPIOx_MODER) */
+#define GPIO_MODER(port) MMIO32(port + 0x00)
+#define GPIOA_MODER GPIO_MODER(GPIOA)
+#define GPIOB_MODER GPIO_MODER(GPIOB)
+#define GPIOC_MODER GPIO_MODER(GPIOC)
+#define GPIOD_MODER GPIO_MODER(GPIOD)
+#define GPIOE_MODER GPIO_MODER(GPIOE)
+#define GPIOF_MODER GPIO_MODER(GPIOF)
+#define GPIOG_MODER GPIO_MODER(GPIOG)
+#define GPIOH_MODER GPIO_MODER(GPIOH)
+#define GPIOI_MODER GPIO_MODER(GPIOI)
+
+/* Port output type register (GPIOx_OTYPER) */
+#define GPIO_OTYPER(port) MMIO32(port + 0x04)
+#define GPIOA_OTYPER GPIO_OTYPER(GPIOA)
+#define GPIOB_OTYPER GPIO_OTYPER(GPIOB)
+#define GPIOC_OTYPER GPIO_OTYPER(GPIOC)
+#define GPIOD_OTYPER GPIO_OTYPER(GPIOD)
+#define GPIOE_OTYPER GPIO_OTYPER(GPIOE)
+#define GPIOF_OTYPER GPIO_OTYPER(GPIOF)
+#define GPIOG_OTYPER GPIO_OTYPER(GPIOG)
+#define GPIOH_OTYPER GPIO_OTYPER(GPIOH)
+#define GPIOI_OTYPER GPIO_OTYPER(GPIOI)
+
+/* Port output speed register (GPIOx_OSPEEDR) */
+#define GPIO_OSPEEDR(port) MMIO32(port + 0x08)
+#define GPIOA_OSPEEDR GPIO_OSPEEDR(GPIOA)
+#define GPIOB_OSPEEDR GPIO_OSPEEDR(GPIOB)
+#define GPIOC_OSPEEDR GPIO_OSPEEDR(GPIOC)
+#define GPIOD_OSPEEDR GPIO_OSPEEDR(GPIOD)
+#define GPIOE_OSPEEDR GPIO_OSPEEDR(GPIOE)
+#define GPIOF_OSPEEDR GPIO_OSPEEDR(GPIOF)
+#define GPIOG_OSPEEDR GPIO_OSPEEDR(GPIOG)
+#define GPIOH_OSPEEDR GPIO_OSPEEDR(GPIOH)
+#define GPIOI_OSPEEDR GPIO_OSPEEDR(GPIOI)
+
+/* Port pull-up/pull-down register (GPIOx_PUPDR) */
+#define GPIO_PUPDR(port) MMIO32(port + 0x0c)
+#define GPIOA_PUPDR GPIO_PUPDR(GPIOA)
+#define GPIOB_PUPDR GPIO_PUPDR(GPIOB)
+#define GPIOC_PUPDR GPIO_PUPDR(GPIOC)
+#define GPIOD_PUPDR GPIO_PUPDR(GPIOD)
+#define GPIOE_PUPDR GPIO_PUPDR(GPIOE)
+#define GPIOF_PUPDR GPIO_PUPDR(GPIOF)
+#define GPIOG_PUPDR GPIO_PUPDR(GPIOG)
+#define GPIOH_PUPDR GPIO_PUPDR(GPIOH)
+#define GPIOI_PUPDR GPIO_PUPDR(GPIOI)
+
+/* Port input data register (GPIOx_IDR) */
+#define GPIO_IDR(port) MMIO32(port + 0x10)
+#define GPIOA_IDR GPIO_IDR(GPIOA)
+#define GPIOB_IDR GPIO_IDR(GPIOB)
+#define GPIOC_IDR GPIO_IDR(GPIOC)
+#define GPIOD_IDR GPIO_IDR(GPIOD)
+#define GPIOE_IDR GPIO_IDR(GPIOE)
+#define GPIOF_IDR GPIO_IDR(GPIOF)
+#define GPIOG_IDR GPIO_IDR(GPIOG)
+#define GPIOH_IDR GPIO_IDR(GPIOH)
+#define GPIOI_IDR GPIO_IDR(GPIOI)
+
+/* Port output data register (GPIOx_ODR) */
+#define GPIO_ODR(port) MMIO32(port + 0x14)
+#define GPIOA_ODR GPIO_ODR(GPIOA)
+#define GPIOB_ODR GPIO_ODR(GPIOB)
+#define GPIOC_ODR GPIO_ODR(GPIOC)
+#define GPIOD_ODR GPIO_ODR(GPIOD)
+#define GPIOE_ODR GPIO_ODR(GPIOE)
+#define GPIOF_ODR GPIO_ODR(GPIOF)
+#define GPIOG_ODR GPIO_ODR(GPIOG)
+#define GPIOH_ODR GPIO_ODR(GPIOH)
+#define GPIOI_ODR GPIO_ODR(GPIOI)
+
+/* Port bit set/reset register (GPIOx_BSRR) */
+#define GPIO_BSRR(port) MMIO32(port + 0x18)
+#define GPIOA_BSRR GPIO_BSRR(GPIOA)
+#define GPIOB_BSRR GPIO_BSRR(GPIOB)
+#define GPIOC_BSRR GPIO_BSRR(GPIOC)
+#define GPIOD_BSRR GPIO_BSRR(GPIOD)
+#define GPIOE_BSRR GPIO_BSRR(GPIOE)
+#define GPIOF_BSRR GPIO_BSRR(GPIOF)
+#define GPIOG_BSRR GPIO_BSRR(GPIOG)
+#define GPIOH_BSRR GPIO_BSRR(GPIOH)
+#define GPIOI_BSRR GPIO_BSRR(GPIOI)
+
+/* Port configuration lock register (GPIOx_LCKR) */
+#define GPIO_LCKR(port) MMIO32(port + 0x1c)
+#define GPIOA_LCKR GPIO_LCKR(GPIOA)
+#define GPIOB_LCKR GPIO_LCKR(GPIOB)
+#define GPIOC_LCKR GPIO_LCKR(GPIOC)
+#define GPIOD_LCKR GPIO_LCKR(GPIOD)
+#define GPIOE_LCKR GPIO_LCKR(GPIOE)
+#define GPIOF_LCKR GPIO_LCKR(GPIOF)
+#define GPIOG_LCKR GPIO_LCKR(GPIOG)
+#define GPIOH_LCKR GPIO_LCKR(GPIOH)
+#define GPIOI_LCKR GPIO_LCKR(GPIOI)
+
+/* Alternate function low register (GPIOx_AFRL) */
+#define GPIO_AFRL(port) MMIO32(port + 0x20)
+#define GPIOA_AFRL GPIO_AFRL(GPIOA)
+#define GPIOB_AFRL GPIO_AFRL(GPIOB)
+#define GPIOC_AFRL GPIO_AFRL(GPIOC)
+#define GPIOD_AFRL GPIO_AFRL(GPIOD)
+#define GPIOE_AFRL GPIO_AFRL(GPIOE)
+#define GPIOF_AFRL GPIO_AFRL(GPIOF)
+#define GPIOG_AFRL GPIO_AFRL(GPIOG)
+#define GPIOH_AFRL GPIO_AFRL(GPIOH)
+#define GPIOI_AFRL GPIO_AFRL(GPIOI)
+
+/* Alternate function high register (GPIOx_AFRH) */
+#define GPIO_AFRH(port) MMIO32(port + 0x24)
+#define GPIOA_AFRH GPIO_AFRH(GPIOA)
+#define GPIOB_AFRH GPIO_AFRH(GPIOB)
+#define GPIOC_AFRH GPIO_AFRH(GPIOC)
+#define GPIOD_AFRH GPIO_AFRH(GPIOD)
+#define GPIOE_AFRH GPIO_AFRH(GPIOE)
+#define GPIOF_AFRH GPIO_AFRH(GPIOF)
+#define GPIOG_AFRH GPIO_AFRH(GPIOG)
+#define GPIOH_AFRH GPIO_AFRH(GPIOH)
+#define GPIOI_AFRH GPIO_AFRH(GPIOI)
+
+/* --- GPIOx_MODER values -------------------------------------------------- */
+
+#define GPIO_MODE(n, mode) (mode << (2 * (n)))
+#define GPIO_MODE_MASK(n) (0x3 << (2 * (n)))
+/** @defgroup gpio_mode GPIO Pin Direction and Analog/Digital Mode
+@ingroup gpio_defines
+@{*/
+#define GPIO_MODE_INPUT 0x0
+#define GPIO_MODE_OUTPUT 0x1
+#define GPIO_MODE_AF 0x2
+#define GPIO_MODE_ANALOG 0x3
+/**@}*/
+
+/* --- GPIOx_OTYPER values ------------------------------------------------- */
+
+/** @defgroup gpio_output_type GPIO Output Pin Driver Type
+@ingroup gpio_defines
+@list Push Pull
+@list Open Drain
+@{*/
+#define GPIO_OTYPE_PP 0x0
+#define GPIO_OTYPE_OD 0x1
+/**@}*/
+
+/* --- GPIOx_OSPEEDR values ------------------------------------------------ */
+
+#define GPIO_OSPEED(n, speed) (speed << (2 * (n)))
+#define GPIO_OSPEED_MASK(n) (0x3 << (2 * (n)))
+/** @defgroup gpio_speed GPIO Output Pin Speed
+@ingroup gpio_defines
+@{*/
+#define GPIO_OSPEED_2MHZ 0x0
+#define GPIO_OSPEED_25MHZ 0x1
+#define GPIO_OSPEED_50MHZ 0x2
+#define GPIO_OSPEED_100MHZ 0x3
+/**@}*/
+
+/* --- GPIOx_PUPDR values -------------------------------------------------- */
+
+#define GPIO_PUPD(n, pupd) (pupd << (2 * (n)))
+#define GPIO_PUPD_MASK(n) (0x3 << (2 * (n)))
+/** @defgroup gpio_pup GPIO Output Pin Pullup
+@ingroup gpio_defines
+@{*/
+#define GPIO_PUPD_NONE 0x0
+#define GPIO_PUPD_PULLUP 0x1
+#define GPIO_PUPD_PULLDOWN 0x2
+/**@}*/
+
+/* --- GPIOx_IDR values ---------------------------------------------------- */
+
+/* GPIOx_IDR[15:0]: IDRy[15:0]: Port input data (y = 0..15) */
+
+/* --- GPIOx_ODR values ---------------------------------------------------- */
+
+/* GPIOx_ODR[15:0]: ODRy[15:0]: Port output data (y = 0..15) */
+
+/* --- GPIOx_BSRR values --------------------------------------------------- */
+
+/* GPIOx_BSRR[31:16]: BRy: Port x reset bit y (y = 0..15) */
+/* GPIOx_BSRR[15:0]: BSy: Port x set bit y (y = 0..15) */
+
+/* --- GPIOx_LCKR values --------------------------------------------------- */
+
+#define GPIO_LCKK (1 << 16)
+/* GPIOx_LCKR[15:0]: LCKy: Port x lock bit y (y = 0..15) */
+
+/* --- GPIOx_AFRL/H values ------------------------------------------------- */
+
+/* Note: AFRL is used for bits 0..7, AFRH is used for 8..15 */
+/* See Datasheet Table 6 (pg. 48) for alternate function mappings. */
+
+#define GPIO_AFR(n, af) (af << ((n) * 4))
+#define GPIO_AFR_MASK(n) (0xf << ((n) * 4))
+/** @defgroup gpio_af_num Alternate Function Pin Selection
+@ingroup gpio_defines
+@{*/
+#define GPIO_AF0 0x0
+#define GPIO_AF1 0x1
+#define GPIO_AF2 0x2
+#define GPIO_AF3 0x3
+#define GPIO_AF4 0x4
+#define GPIO_AF5 0x5
+#define GPIO_AF6 0x6
+#define GPIO_AF7 0x7
+#define GPIO_AF8 0x8
+#define GPIO_AF9 0x9
+#define GPIO_AF10 0xa
+#define GPIO_AF11 0xb
+#define GPIO_AF12 0xc
+#define GPIO_AF13 0xd
+#define GPIO_AF14 0xe
+#define GPIO_AF15 0xf
+/**@}*/
+
+/* Note: EXTI source selection is now in the SYSCFG peripheral. */
+
+/* --- Function prototypes ------------------------------------------------- */
+
+BEGIN_DECLS
+
+/*
+ * Note: The F2 and F4 series have a completely new GPIO peripheral with different
+ * configuration options. Here we implement a different API partly to more
+ * closely match the peripheral capabilities and also to deliberately break
+ * compatibility with old F1 code so there is no confusion with similar
+ * sounding functions that have very different functionality.
+ */
+
+void gpio_mode_setup(u32 gpioport, u8 mode, u8 pull_up_down, u16 gpios);
+void gpio_set_output_options(u32 gpioport, u8 otype, u8 speed, u16 gpios);
+void gpio_set_af(u32 gpioport, u8 alt_func_num, u16 gpios);
+
+END_DECLS
+/**@}*/
+#endif
+
diff --git a/include/libopencm3/stm32/gpio.h b/include/libopencm3/stm32/gpio.h
new file mode 100644
index 0000000..8037cd2
--- /dev/null
+++ b/include/libopencm3/stm32/gpio.h
@@ -0,0 +1,29 @@
+/* This provides unification of code over STM32F subfamilies */
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if defined(STM32F1)
+# include <libopencm3/stm32/f1/gpio.h>
+#elif defined(STM32F2)
+# include <libopencm3/stm32/f2/gpio.h>
+#elif defined(STM32F4)
+# include <libopencm3/stm32/f4/gpio.h>
+#else
+# error "stm32 family not defined."
+#endif
+
diff --git a/lib/stm32/common/gpio_common_all.c b/lib/stm32/common/gpio_common_all.c
new file mode 100644
index 0000000..d23e415
--- /dev/null
+++ b/lib/stm32/common/gpio_common_all.c
@@ -0,0 +1,139 @@
+/** @addtogroup gpio_file */
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define WEAK __attribute__ ((weak))
+
+#include <libopencm3/stm32/gpio.h>
+
+/**@{*/
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Set a Group of Pins Atomic
+
+Set one or more pins of the given GPIO port to 1 in an atomic operation.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be changed, use logical OR '|' to separate them.
+*/
+void gpio_set(u32 gpioport, u16 gpios)
+{
+ GPIO_BSRR(gpioport) = gpios;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Clear a Group of Pins Atomic
+
+Clear one or more pins of the given GPIO port to 0 in an atomic operation.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be changed, use logical OR '|' to separate them.
+*/
+void gpio_clear(u32 gpioport, u16 gpios)
+{
+ GPIO_BSRR(gpioport) = (gpios << 16);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Read a Group of Pins.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be read, use logical OR '|' to separate them.
+@return Unsigned int16 value of the pin values. The bit position of the pin value
+ returned corresponds to the pin number.
+*/
+u16 gpio_get(u32 gpioport, u16 gpios)
+{
+ return gpio_port_read(gpioport) & gpios;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Toggle a Group of Pins
+
+Toggle one or more pins of the given GPIO port. This is not an atomic operation.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be changed, use logical OR '|' to separate them.
+*/
+void gpio_toggle(u32 gpioport, u16 gpios)
+{
+ GPIO_ODR(gpioport) ^= gpios;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Read from a Port
+
+Read the current value of the given GPIO port. Only the lower 16 bits contain
+valid pin data.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@return Unsigned int16. The value held in the specified GPIO port.
+*/
+u16 gpio_port_read(u32 gpioport)
+{
+ return (u16)GPIO_IDR(gpioport);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Write to a Port
+
+Write a value to the given GPIO port.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] data Unsigned int16. The value to be written to the GPIO port.
+*/
+void gpio_port_write(u32 gpioport, u16 data)
+{
+ GPIO_ODR(gpioport) = data;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Lock the Configuration of a Group of Pins
+
+The configuration of one or more pins of the given GPIO port is locked. There is
+no mechanism to unlock these via software. Unlocking occurs at the next reset.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be locked, use logical OR '|' to separate them.
+*/
+void gpio_port_config_lock(u32 gpioport, u16 gpios)
+{
+ u32 reg32;
+
+ /* Special "Lock Key Writing Sequence", see datasheet. */
+ GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
+ GPIO_LCKR(gpioport) = ~GPIO_LCKK & gpios; /* Clear LCKK. */
+ GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
+ reg32 = GPIO_LCKR(gpioport); /* Read LCKK. */
+ reg32 = GPIO_LCKR(gpioport); /* Read LCKK again. */
+
+ /* Tell the compiler the variable is actually used. It will get optimized out anyways. */
+ reg32 = reg32;
+
+ /* If (reg32 & GPIO_LCKK) is true, the lock is now active. */
+}
+
+/**@}*/
+
diff --git a/lib/stm32/common/gpio_common_f24.c b/lib/stm32/common/gpio_common_f24.c
new file mode 100644
index 0000000..2a7c127
--- /dev/null
+++ b/lib/stm32/common/gpio_common_f24.c
@@ -0,0 +1,195 @@
+/** @addtogroup gpio_file
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
+@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
+
+@date 18 August 2012
+
+Each I/O port has 16 individually configurable bits. Many I/O pins share GPIO
+functionality with a number of alternate functions and must be configured to the
+alternate function mode if these are to be accessed. A feature is available to
+remap alternative functions to a limited set of alternative pins in the event
+of a clash of requirements.
+
+The data registers associated with each port for input and output are 32 bit with
+the upper 16 bits unused. The output buffer must be written as a 32 bit word, but
+individual bits may be set or reset separately in atomic operations to avoid race
+conditions during interrupts. Bits may also be individually locked to prevent
+accidental configuration changes. Once locked the configuration cannot be changed
+until after the next reset.
+
+Each port bit can be configured as analog or digital input, the latter can be
+floating or pulled up or down. As outputs they can be configured as either
+push-pull or open drain, digital I/O or alternate function, and with maximum
+output speeds of 2MHz, 10MHz, or 50MHz.
+
+On reset all ports are configured as digital floating input.
+
+@section gpio_api_ex Basic GPIO Handling API.
+
+Example 1: Push-pull digital output actions on ports C2 and C9
+
+@code
+ gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT,
+ GPIO_PUPD_PULLUP, GPIO2 | GPIO9);
+ gpio_output_options((GPIOC, GPIO_OTYPE_PP,
+ GPIO_OSPEED_25MHZ, GPIO2 | GPIO9);
+ gpio_set(GPIOC, GPIO2 | GPIO9);
+ gpio_clear(GPIOC, GPIO2);
+ gpio_toggle(GPIOC, GPIO2 | GPIO9);
+ gpio_port_write(GPIOC, 0x204);
+@endcode
+
+Example 1: Digital input on port C12
+
+@code
+ gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT,
+ GPIO_PUPD_PULLUP, GPIO12);
+ reg16 = gpio_port_read(GPIOC);
+@endcode
+
+LGPL License Terms @ref lgpl_license
+*/
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**@{*/
+
+#include <libopencm3/stm32/common/gpio_common_all.h>
+#include <libopencm3/stm32/gpio.h>
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Set GPIO Pin Mode
+
+Sets the Pin Direction and Analog/Digital Mode, and Output Pin Pullup,
+for a set of GPIO pins on a given GPIO port.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] mode Unsigned int8. Pin mode @ref gpio_mode
+@param[in] pull_up_down Unsigned int8. Pin pullup/pulldown configuration @ref gpio_pup
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be set, use logical OR '|' to separate them.
+*/
+void gpio_mode_setup(u32 gpioport, u8 mode, u8 pull_up_down, u16 gpios)
+{
+ u16 i;
+ u32 moder, pupd;
+
+ /*
+ * We want to set the config only for the pins mentioned in gpios,
+ * but keeping the others, so read out the actual config first.
+ */
+ moder = GPIO_MODER(gpioport);
+ pupd = GPIO_PUPDR(gpioport);
+
+ for (i = 0; i < 16; i++) {
+ if (!((1 << i) & gpios))
+ continue;
+
+ moder &= ~GPIO_MODE_MASK(i);
+ moder |= GPIO_MODE(i, mode);
+ pupd &= ~GPIO_PUPD_MASK(i);
+ pupd |= GPIO_PUPD(i, pull_up_down);
+ }
+
+ /* Set mode and pull up/down control registers. */
+ GPIO_MODER(gpioport) = moder;
+ GPIO_PUPDR(gpioport) = pupd;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Set GPIO Output Options
+
+When the pin is set to output mode, this sets the configuration (analog/digital and
+open drain/push pull) and speed, for a set of GPIO pins on a given GPIO port.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] otype Unsigned int8. Pin output type @ref gpio_output_type
+@param[in] speed Unsigned int8. Pin speed @ref gpio_speed
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be set, use logical OR '|' to separate them.
+*/
+void gpio_set_output_options(u32 gpioport, u8 otype, u8 speed, u16 gpios)
+{
+ u16 i;
+ u32 ospeedr;
+
+ if (otype == 0x1)
+ GPIO_OTYPER(gpioport) |= gpios;
+ else
+ GPIO_OTYPER(gpioport) &= ~gpios;
+
+ ospeedr = GPIO_OSPEEDR(gpioport);
+
+ for (i = 0; i < 16; i++) {
+ if (!((1 << i) & gpios))
+ continue;
+ ospeedr &= ~GPIO_OSPEED_MASK(i);
+ ospeedr |= GPIO_OSPEED(i, speed);
+ }
+
+ GPIO_OSPEEDR(gpioport) = ospeedr;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Set GPIO Alternate Function Selection
+
+Set the alternate function mapping number for each pin. Most pins have alternate
+functions associated with them. When set to AF mode, a pin may be used for one of
+its allocated alternate functions selected by the number given here. To determine
+the number to be used for the desired function refer to the individual datasheet
+for the particular device. A table is given under the Pin Selection chapter.
+
+Note that a number of pins may be set but only with a single AF number. In practice
+this would rarely be useful as each pin is likely to require a different number.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] alt_func_num Unsigned int8. Pin alternate function number @ref gpio_af_num
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be set, use logical OR '|' to separate them.
+*/
+void gpio_set_af(u32 gpioport, u8 alt_func_num, u16 gpios)
+{
+ u16 i;
+ u32 afrl, afrh;
+
+ afrl = GPIO_AFRL(gpioport);
+ afrh = GPIO_AFRH(gpioport);
+
+ for (i = 0; i < 8; i++) {
+ if (!((1 << i) & gpios))
+ continue;
+ afrl &= ~GPIO_AFR_MASK(i);
+ afrl |= GPIO_AFR(i, alt_func_num);
+ }
+
+ for (i = 8; i < 16; i++) {
+ if (!((1 << i) & gpios))
+ continue;
+ afrl &= ~GPIO_AFR_MASK(i - 8);
+ afrh |= GPIO_AFR(i - 8, alt_func_num);
+ }
+
+ GPIO_AFRL(gpioport) = afrl;
+ GPIO_AFRH(gpioport) = afrh;
+}
+/**@}*/
+