aboutsummaryrefslogtreecommitdiffstats
path: root/libmaple/stm32f2-f4
diff options
context:
space:
mode:
Diffstat (limited to 'libmaple/stm32f2-f4')
-rw-r--r--libmaple/stm32f2-f4/adc.c84
-rw-r--r--libmaple/stm32f2-f4/dma.c504
-rw-r--r--libmaple/stm32f2-f4/exti.c33
-rw-r--r--libmaple/stm32f2-f4/fsmc.c96
-rw-r--r--libmaple/stm32f2-f4/gpio.c194
-rw-r--r--libmaple/stm32f2-f4/i2c.c99
-rw-r--r--libmaple/stm32f2-f4/include/series/adc.h335
-rw-r--r--libmaple/stm32f2-f4/include/series/dac.h94
-rw-r--r--libmaple/stm32f2-f4/include/series/dma.h810
-rw-r--r--libmaple/stm32f2-f4/include/series/exti.h46
-rw-r--r--libmaple/stm32f2-f4/include/series/flash.h206
-rw-r--r--libmaple/stm32f2-f4/include/series/gpio.h264
-rw-r--r--libmaple/stm32f2-f4/include/series/i2c.h80
-rw-r--r--libmaple/stm32f2-f4/include/series/nvic.h160
-rw-r--r--libmaple/stm32f2-f4/include/series/pwr.h73
-rw-r--r--libmaple/stm32f2-f4/include/series/rcc.h955
-rw-r--r--libmaple/stm32f2-f4/include/series/spi.h88
-rw-r--r--libmaple/stm32f2-f4/include/series/stm32.h109
-rw-r--r--libmaple/stm32f2-f4/include/series/timer.h176
-rw-r--r--libmaple/stm32f2-f4/include/series/usart.h111
-rw-r--r--libmaple/stm32f2-f4/isrs.S329
-rw-r--r--libmaple/stm32f2-f4/rcc.c175
-rw-r--r--libmaple/stm32f2-f4/rules.mk40
-rw-r--r--libmaple/stm32f2-f4/spi.c88
-rw-r--r--libmaple/stm32f2-f4/syscfg.c78
-rw-r--r--libmaple/stm32f2-f4/timer.c171
-rw-r--r--libmaple/stm32f2-f4/usart.c204
-rw-r--r--libmaple/stm32f2-f4/vector_table.S138
28 files changed, 5740 insertions, 0 deletions
diff --git a/libmaple/stm32f2-f4/adc.c b/libmaple/stm32f2-f4/adc.c
new file mode 100644
index 0000000..a400d7b
--- /dev/null
+++ b/libmaple/stm32f2-f4/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/adc.c
+ * @brief STM32F2 ADC.
+ */
+
+#include <libmaple/adc.h>
+#include <libmaple/gpio.h>
+
+/*
+ * 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;
+
+static 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_config_gpio(const adc_dev *ignored, 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-f4/dma.c b/libmaple/stm32f2-f4/dma.c
new file mode 100644
index 0000000..26e87b9
--- /dev/null
+++ b/libmaple/stm32f2-f4/dma.c
@@ -0,0 +1,504 @@
+/******************************************************************************
+ * 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/dma.c
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F2 DMA support.
+ */
+
+#include <libmaple/dma.h>
+#include <libmaple/bitband.h>
+#include <libmaple/util.h>
+
+/* Hack to ensure inlining in dma_irq_handler() */
+#define DMA_GET_HANDLER(dev, tube) (dev->handlers[tube].handler)
+#include "dma_private.h"
+
+/*
+ * Devices
+ */
+
+static dma_dev dma1 = {
+ .regs = DMA1_BASE,
+ .clk_id = RCC_DMA1,
+ .handlers = {{ .handler = NULL, .irq_line = NVIC_DMA1_STREAM0 },
+ { .handler = NULL, .irq_line = NVIC_DMA1_STREAM1 },
+ { .handler = NULL, .irq_line = NVIC_DMA1_STREAM2 },
+ { .handler = NULL, .irq_line = NVIC_DMA1_STREAM3 },
+ { .handler = NULL, .irq_line = NVIC_DMA1_STREAM4 },
+ { .handler = NULL, .irq_line = NVIC_DMA1_STREAM5 },
+ { .handler = NULL, .irq_line = NVIC_DMA1_STREAM6 },
+ { .handler = NULL, .irq_line = NVIC_DMA1_STREAM7 }},
+};
+dma_dev *DMA1 = &dma1;
+
+static dma_dev dma2 = {
+ .regs = DMA2_BASE,
+ .clk_id = RCC_DMA2,
+ .handlers = {{ .handler = NULL, .irq_line = NVIC_DMA2_STREAM0 },
+ { .handler = NULL, .irq_line = NVIC_DMA2_STREAM1 },
+ { .handler = NULL, .irq_line = NVIC_DMA2_STREAM2 },
+ { .handler = NULL, .irq_line = NVIC_DMA2_STREAM3 },
+ { .handler = NULL, .irq_line = NVIC_DMA2_STREAM4 },
+ { .handler = NULL, .irq_line = NVIC_DMA2_STREAM5 },
+ { .handler = NULL, .irq_line = NVIC_DMA2_STREAM6 },
+ { .handler = NULL, .irq_line = NVIC_DMA2_STREAM7 }},
+};
+dma_dev *DMA2 = &dma2;
+
+/*
+ * Helpers for dealing with dma_request_src's bit encoding (see the
+ * comments in the dma_request_src definition).
+ */
+
+/* rcc_clk_id of dma_dev which supports src. */
+static __always_inline rcc_clk_id src_clk_id(dma_request_src src) {
+ return (rcc_clk_id)(((uint32)src >> 3) & 0x3F);
+}
+
+/* Bit vector of streams supporting src (e.g., bit 0 set => DMA_S0 support). */
+static __always_inline uint32 src_stream_mask(dma_request_src src) {
+ return ((uint32)src >> 10) & 0xFF;
+}
+
+/* Channel corresponding to src. */
+static __always_inline dma_channel src_channel(dma_request_src src) {
+ return (dma_channel)(src & 0x7);
+}
+
+/*
+ * Routines
+ */
+
+/* For convenience */
+#define ASSERT_NOT_ENABLED(dev, tube) ASSERT(!dma_is_enabled(dev, tube))
+
+/* Helpers for dma_tube_cfg() */
+static int preconfig_check(dma_dev *dev, dma_tube tube, dma_tube_config *cfg);
+static int postconfig_check(dma_tube_reg_map *dummy, dma_tube_config *cfg);
+static int config_fifo(dma_tube_reg_map *dummy, dma_tube_config *cfg);
+static int config_src_dst(dma_tube_reg_map *dummy, dma_tube_config *cfg);
+static void copy_regs(dma_tube_reg_map *src, dma_tube_reg_map *dst);
+
+int dma_tube_cfg(dma_dev *dev, dma_tube tube, dma_tube_config *cfg) {
+ dma_tube_reg_map dummy_regs;
+ dma_tube_reg_map *tregs = dma_tube_regs(dev, tube);
+ int ret;
+
+ /* Initial error checking. */
+ ret = preconfig_check(dev, tube, cfg);
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* Disable `tube' as per RM0033. */
+ dma_disable(dev, tube);
+ dma_clear_isr_bits(dev, tube);
+
+ /* Don't write to tregs until we've decided `cfg' is really OK,
+ * so as not to make a half-formed mess if we have to error out. */
+ copy_regs(tregs, &dummy_regs);
+
+ /* Try to reconfigure `tube', bailing on error. */
+ ret = config_fifo(&dummy_regs, cfg);
+ if (ret < 0) {
+ return ret;
+ }
+ ret = config_src_dst(&dummy_regs, cfg);
+ if (ret < 0) {
+ return ret;
+ }
+ dummy_regs.SNDTR = cfg->tube_nr_xfers;
+ ret = postconfig_check(&dummy_regs, cfg);
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* Ok, we're good. Commit to the new configuration. */
+ copy_regs(&dummy_regs, tregs);
+ return ret;
+}
+
+void dma_set_priority(dma_dev *dev, dma_stream stream, dma_priority priority) {
+ dma_tube_reg_map *tregs = dma_tube_regs(dev, stream);
+ uint32 scr;
+ ASSERT_NOT_ENABLED(dev, stream);
+ scr = tregs->SCR;
+ scr &= ~DMA_SCR_PL;
+ scr |= (priority << 16);
+ tregs->SCR = scr;
+}
+
+void dma_set_num_transfers(dma_dev *dev, dma_tube tube, uint16 num_transfers) {
+ dma_tube_reg_map *tregs = dma_tube_regs(dev, tube);
+ ASSERT_NOT_ENABLED(dev, tube);
+ tregs->SNDTR = num_transfers;
+}
+
+/**
+ * @brief Set memory 0 or memory 1 address.
+ *
+ * This is a general function for setting one of the two memory
+ * addresses available on the double-buffered STM32F2 DMA controllers.
+ *
+ * @param dev DMA device
+ * @param tube Tube on dev.
+ * @param n If 0, set memory 0 address. If 1, set memory 1 address.
+ * @param address Address to set
+ */
+void dma_set_mem_n_addr(dma_dev *dev, dma_tube tube, int n,
+ __io void *address) {
+ dma_tube_reg_map *tregs = dma_tube_regs(dev, tube);
+ uint32 addr = (uint32)address;
+
+ ASSERT_NOT_ENABLED(dev, tube);
+ if (n) {
+ tregs->SM1AR = addr;
+ } else {
+ tregs->SM0AR = addr;
+ }
+}
+
+void dma_set_per_addr(dma_dev *dev, dma_tube tube, __io void *address) {
+ dma_tube_reg_map *tregs = dma_tube_regs(dev, tube);
+ ASSERT_NOT_ENABLED(dev, tube);
+ tregs->SPAR = (uint32)address;
+}
+
+/**
+ * @brief Enable a stream's FIFO.
+ *
+ * You may only call this function when the stream is disabled.
+ *
+ * @param dev DMA device
+ * @param tube Stream whose FIFO to enable.
+ */
+void dma_enable_fifo(dma_dev *dev, dma_tube tube) {
+ ASSERT_NOT_ENABLED(dev, tube);
+ bb_peri_set_bit(&(dma_tube_regs(dev, tube)->SFCR), DMA_SFCR_DMDIS_BIT, 1);
+}
+
+/**
+ * @brief Disable a stream's FIFO.
+ *
+ * You may only call this function when the stream is disabled.
+ *
+ * @param dev DMA device
+ * @param tube Stream whose FIFO to disable.
+ */
+void dma_disable_fifo(dma_dev *dev, dma_tube tube) {
+ ASSERT_NOT_ENABLED(dev, tube);
+ bb_peri_set_bit(&(dma_tube_regs(dev, tube)->SFCR), DMA_SFCR_DMDIS_BIT, 0);
+}
+
+void dma_attach_interrupt(dma_dev *dev, dma_tube tube,
+ void (*handler)(void)) {
+ dev->handlers[tube].handler = handler;
+ nvic_irq_enable(dev->handlers[tube].irq_line);
+}
+
+void dma_detach_interrupt(dma_dev *dev, dma_tube tube) {
+ nvic_irq_disable(dev->handlers[tube].irq_line);
+ dev->handlers[tube].handler = NULL;
+}
+
+void dma_enable(dma_dev *dev, dma_tube tube) {
+ dma_tube_reg_map *tregs = dma_tube_regs(dev, tube);
+ bb_peri_set_bit(&tregs->SCR, DMA_SCR_EN_BIT, 1);
+}
+
+void dma_disable(dma_dev *dev, dma_tube tube) {
+ dma_tube_reg_map *tregs = dma_tube_regs(dev, tube);
+ bb_peri_set_bit(&tregs->SCR, DMA_SCR_EN_BIT, 0);
+ /* The stream might not get disabled immediately, so wait. */
+ while (tregs->SCR & DMA_SCR_EN)
+ ;
+}
+
+dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_tube tube) {
+ /* TODO: does it still make sense to have this function? We should
+ * probably just be returning the ISR bits, with some defines to
+ * pull the flags out. The lack of masked status bits is an
+ * annoyance that would require documentation to solve, though. */
+ uint8 status_bits = dma_get_isr_bits(dev, tube);
+ dma_clear_isr_bits(dev, tube);
+ ASSERT(status_bits); /* Or something's very wrong */
+ /* Don't change the order of these if statements. */
+ if (status_bits & 0x0) {
+ return DMA_TRANSFER_FIFO_ERROR;
+ } else if (status_bits & 0x4) {
+ return DMA_TRANSFER_DME_ERROR;
+ } else if (status_bits & 0x8) {
+ return DMA_TRANSFER_ERROR;
+ } else if (status_bits & 0x20) {
+ return DMA_TRANSFER_COMPLETE;
+ } else if (status_bits & 0x10) {
+ return DMA_TRANSFER_HALF_COMPLETE;
+ }
+
+ /* Something's wrong; one of those bits should have been set. Fail
+ * an assert, and mimic the error behavior in case of a high debug
+ * level. */
+ ASSERT(0);
+ dma_disable(dev, tube);
+ return DMA_TRANSFER_ERROR;
+}
+
+/*
+ * IRQ handlers
+ */
+
+void __irq_dma1_stream0(void) {
+ dma_irq_handler(DMA1, DMA_S0);
+}
+
+void __irq_dma1_stream1(void) {
+ dma_irq_handler(DMA1, DMA_S1);
+}
+
+void __irq_dma1_stream2(void) {
+ dma_irq_handler(DMA1, DMA_S2);
+}
+
+void __irq_dma1_stream3(void) {
+ dma_irq_handler(DMA1, DMA_S3);
+}
+
+void __irq_dma1_stream4(void) {
+ dma_irq_handler(DMA1, DMA_S4);
+}
+
+void __irq_dma1_stream5(void) {
+ dma_irq_handler(DMA1, DMA_S5);
+}
+
+void __irq_dma1_stream6(void) {
+ dma_irq_handler(DMA1, DMA_S6);
+}
+
+void __irq_dma1_stream7(void) {
+ dma_irq_handler(DMA1, DMA_S7);
+}
+
+void __irq_dma2_stream0(void) {
+ dma_irq_handler(DMA2, DMA_S0);
+}
+
+void __irq_dma2_stream1(void) {
+ dma_irq_handler(DMA2, DMA_S1);
+}
+
+void __irq_dma2_stream2(void) {
+ dma_irq_handler(DMA2, DMA_S2);
+}
+
+void __irq_dma2_stream3(void) {
+ dma_irq_handler(DMA2, DMA_S3);
+}
+
+void __irq_dma2_stream4(void) {
+ dma_irq_handler(DMA2, DMA_S4);
+}
+
+void __irq_dma2_stream5(void) {
+ dma_irq_handler(DMA2, DMA_S5);
+}
+
+void __irq_dma2_stream6(void) {
+ dma_irq_handler(DMA2, DMA_S6);
+}
+
+void __irq_dma2_stream7(void) {
+ dma_irq_handler(DMA2, DMA_S7);
+}
+
+/*
+ * Auxiliary routines for dma_tube_cfg()
+ */
+
+/* Is addr acceptable for use as DMA src/dst? */
+static int cfg_mem_ok(__io void *addr) {
+ enum dma_atype atype = _dma_addr_type(addr);
+ return atype == DMA_ATYPE_MEM || atype == DMA_ATYPE_PER;
+}
+
+/* Is src -> dst a reasonable combination of [MEM,PER] -> [MEM,PER]? */
+static int cfg_dir_ok(dma_dev *dev, __io void *src, __io void *dst) {
+ switch (_dma_addr_type(dst)) {
+ case DMA_ATYPE_MEM:
+ /* Only DMA2 can do memory-to-memory */
+ return ((_dma_addr_type(src) == DMA_ATYPE_PER) ||
+ (dev->clk_id == RCC_DMA2));
+ case DMA_ATYPE_PER:
+ /* Peripheral-to-peripheral is illegal */
+ return _dma_addr_type(src) == DMA_ATYPE_PER;
+ default: /* Can't happen */
+ ASSERT(0);
+ return 0;
+ }
+}
+
+/* Initial sanity check for dma_tube_cfg() */
+static int preconfig_check(dma_dev *dev, dma_tube tube,
+ dma_tube_config *cfg) {
+ if (!(src_stream_mask(cfg->tube_req_src) & (1U << tube))) {
+ /* ->tube_req_src not supported by stream */
+ return -DMA_TUBE_CFG_EREQ;
+ }
+ if (cfg->tube_nr_xfers > 65535) {
+ /* That's too many. */
+ return -DMA_TUBE_CFG_ENDATA;
+ }
+ if (src_clk_id(cfg->tube_req_src) != dev->clk_id) {
+ /* ->tube_req_src not supported by dev */
+ return -DMA_TUBE_CFG_EDEV;
+ }
+ if (!cfg_mem_ok(cfg->tube_src)) {
+ return -DMA_TUBE_CFG_ESRC;
+ }
+ if (!cfg_mem_ok(cfg->tube_dst)) {
+ return -DMA_TUBE_CFG_EDST;
+ }
+ if (!cfg_dir_ok(dev, cfg->tube_src, cfg->tube_dst)) {
+ return -DMA_TUBE_CFG_EDIR;
+ }
+ return DMA_TUBE_CFG_SUCCESS;
+}
+
+static int config_fifo(dma_tube_reg_map *dummy, dma_tube_config *cfg) {
+ /* TODO: FIFO configuration based on cfg->target_data */
+ uint32 sfcr = dummy->SFCR;
+ sfcr &= ~DMA_SFCR_FEIE;
+ sfcr |= (cfg->tube_flags & DMA_CFG_FIFO_ERR_IE) ? DMA_SFCR_FEIE : 0;
+ dummy->SFCR = sfcr;
+ return DMA_TUBE_CFG_SUCCESS;
+}
+
+/* Helper for configuring (DMA_SxCR) */
+#define BITS_WE_CARE_ABOUT \
+ (DMA_SCR_CHSEL | DMA_SCR_MBURST | DMA_SCR_PBURST | DMA_SCR_PINCOS | \
+ DMA_SCR_MINC | DMA_SCR_PINC | DMA_SCR_CIRC | DMA_SCR_DIR | \
+ DMA_SCR_PFCTRL | DMA_SCR_TCIE | DMA_SCR_HTIE | DMA_SCR_TEIE | \
+ DMA_SCR_DMEIE)
+static inline void config_scr(dma_tube_reg_map *dummy, dma_tube_config *cfg,
+ unsigned src_shift, uint32 src_inc,
+ unsigned dst_shift, uint32 dst_inc,
+ uint32 dir) {
+ /* These would go here if we supported them: MBURST, PBURST,
+ * PINCOS, PFCTRL. We explicitly choose low priority, and double
+ * buffering belongs elsewhere, I think. [mbolivar] */
+ uint32 flags = cfg->tube_flags & BITS_WE_CARE_ABOUT;
+ uint32 scr = dummy->SCR;
+ scr &= ~(BITS_WE_CARE_ABOUT | DMA_SCR_PL);
+ scr |= (/* CHSEL */
+ (src_channel(cfg->tube_req_src) << 25) |
+ /* MSIZE/PSIZE */
+ (cfg->tube_src_size << src_shift) |
+ (cfg->tube_dst_size << dst_shift) |
+ /* MINC/PINC */
+ ((cfg->tube_flags & DMA_CFG_SRC_INC) ? src_inc : 0) |
+ ((cfg->tube_flags & DMA_CFG_DST_INC) ? dst_inc : 0) |
+ /* DIR */
+ dir |
+ /* Other flags carried by cfg->tube_flags */
+ flags);
+ dummy->SCR = scr;
+}
+#undef BITS_WE_CARE_ABOUT
+
+/* Helper for when cfg->tube_dst is memory */
+static int config_to_mem(dma_tube_reg_map *dummy, dma_tube_config *cfg) {
+ uint32 dir = (_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM ?
+ DMA_SCR_DIR_MEM_TO_MEM : DMA_SCR_DIR_PER_TO_MEM);
+
+ if ((dir == DMA_SCR_DIR_MEM_TO_MEM) && (cfg->tube_flags & DMA_CFG_CIRC)) {
+ return -DMA_TUBE_CFG_ECFG; /* Can't do DMA_CFG_CIRC and mem->mem. */
+ }
+
+ config_scr(dummy, cfg, 11, DMA_SCR_PINC, 13, DMA_SCR_MINC, dir);
+ dummy->SPAR = (uint32)cfg->tube_src;
+ dummy->SM0AR = (uint32)cfg->tube_dst;
+ return DMA_TUBE_CFG_SUCCESS;
+}
+
+/* Helper for when cfg->tube_src is peripheral */
+static int config_to_per(dma_tube_reg_map *dummy, dma_tube_config *cfg) {
+ config_scr(dummy, cfg, 13, DMA_SCR_MINC, 11, DMA_SCR_PINC,
+ DMA_SCR_DIR_MEM_TO_PER);
+ dummy->SM0AR = (uint32)cfg->tube_src;
+ dummy->SPAR = (uint32)cfg->tube_dst;
+ return DMA_TUBE_CFG_SUCCESS;
+}
+
+/* Configures SCR, SPAR, SM0AR, and checks that the result is OK. */
+static int config_src_dst(dma_tube_reg_map *dummy, dma_tube_config *cfg) {
+ switch (_dma_addr_type(cfg->tube_dst)) {
+ case DMA_ATYPE_MEM:
+ return config_to_mem(dummy, cfg);
+ case DMA_ATYPE_PER:
+ return config_to_per(dummy, cfg);
+ case DMA_ATYPE_OTHER:
+ default: /* shut up, GCC */
+ /* Can't happen */
+ ASSERT(0);
+ return -DMA_TUBE_CFG_ECFG;
+ }
+}
+
+/* Final checks we can only perform when fully configured */
+static int postconfig_check(dma_tube_reg_map *dummy, dma_tube_config *cfg) {
+ /* TODO add dma_get_[mem,per]_size() and use them here */
+ /* msize and psize are in bytes here: */
+ uint32 scr = dummy->SCR;
+ uint32 msize = 1U << ((scr >> 13) & 0x3);
+ uint32 psize = 1U << ((scr >> 11) & 0x3);
+
+ /* Ensure NDT will work with PSIZE/MSIZE.
+ *
+ * RM0033 specifies that PSIZE, MSIZE, and NDT must be such that
+ * the last transfer completes; i.e. that if PSIZE < MSIZE, then
+ * NDT is a multiple of MSIZE/PSIZE. See e.g. Table 27. */
+ if ((psize < msize) && (cfg->tube_nr_xfers % (msize / psize))) {
+ return -DMA_TUBE_CFG_ENDATA;
+ }
+
+ /* Direct mode is only possible if MSIZE == PSIZE. */
+ if ((msize != psize) && !(dummy->SFCR & DMA_SFCR_DMDIS)) {
+ return -DMA_TUBE_CFG_ESIZE;
+ }
+
+ return DMA_TUBE_CFG_SUCCESS;
+}
+
+/* Convenience for dealing with dummy registers */
+static void copy_regs(dma_tube_reg_map *src, dma_tube_reg_map *dst) {
+ dst->SCR = src->SCR;
+ dst->SNDTR = src->SNDTR;
+ dst->SPAR = src->SPAR;
+ dst->SM0AR = src->SM0AR;
+ dst->SFCR = src->SFCR;
+}
diff --git a/libmaple/stm32f2-f4/exti.c b/libmaple/stm32f2-f4/exti.c
new file mode 100644
index 0000000..208415f
--- /dev/null
+++ b/libmaple/stm32f2-f4/exti.c
@@ -0,0 +1,33 @@
+/******************************************************************************
+ * 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 <libmaple/exti.h>
+#include <libmaple/syscfg.h>
+#include "exti_private.h"
+
+void exti_select(exti_num num, exti_cfg cfg) {
+ exti_do_select(&SYSCFG_BASE->EXTICR[num / 4], num, cfg);
+}
diff --git a/libmaple/stm32f2-f4/fsmc.c b/libmaple/stm32f2-f4/fsmc.c
new file mode 100644
index 0000000..4ee23fa
--- /dev/null
+++ b/libmaple/stm32f2-f4/fsmc.c
@@ -0,0 +1,96 @@
+/******************************************************************************
+ * 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/fsmc.c
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F2 FSMC support.
+ */
+
+#include <libmaple/stm32.h>
+
+#if STM32_HAVE_FSMC /* Don't try building the rest for MCUs without FSMC */
+
+#include <libmaple/fsmc.h>
+#include <libmaple/gpio.h>
+
+#define CONFIG_GPIO(dev, bit) \
+ do { \
+ gpio_set_modef(dev, bit, GPIO_MODE_AF, GPIO_MODEF_SPEED_HIGH); \
+ gpio_set_af(dev, bit, GPIO_AF_FSMC_SDIO_OTG_FS); \
+ } while (0)
+void fsmc_sram_init_gpios(void) {
+ /* Data lines... */
+ CONFIG_GPIO(GPIOD, 0);
+ CONFIG_GPIO(GPIOD, 1);
+ CONFIG_GPIO(GPIOD, 8);
+ CONFIG_GPIO(GPIOD, 9);
+ CONFIG_GPIO(GPIOD, 10);
+ CONFIG_GPIO(GPIOD, 14);
+ CONFIG_GPIO(GPIOD, 15);
+ CONFIG_GPIO(GPIOE, 7);
+ CONFIG_GPIO(GPIOE, 8);
+ CONFIG_GPIO(GPIOE, 9);
+ CONFIG_GPIO(GPIOE, 10);
+ CONFIG_GPIO(GPIOE, 11);
+ CONFIG_GPIO(GPIOE, 12);
+ CONFIG_GPIO(GPIOE, 13);
+ CONFIG_GPIO(GPIOE, 14);
+ CONFIG_GPIO(GPIOE, 15);
+
+ /* Address lines... */
+ CONFIG_GPIO(GPIOD, 11);
+ CONFIG_GPIO(GPIOD, 12);
+ CONFIG_GPIO(GPIOD, 13);
+ CONFIG_GPIO(GPIOF, 0);
+ CONFIG_GPIO(GPIOF, 1);
+ CONFIG_GPIO(GPIOF, 2);
+ CONFIG_GPIO(GPIOF, 3);
+ CONFIG_GPIO(GPIOF, 4);
+ CONFIG_GPIO(GPIOF, 5);
+ CONFIG_GPIO(GPIOF, 12);
+ CONFIG_GPIO(GPIOF, 13);
+ CONFIG_GPIO(GPIOF, 14);
+ CONFIG_GPIO(GPIOF, 15);
+ CONFIG_GPIO(GPIOG, 0);
+ CONFIG_GPIO(GPIOG, 1);
+ CONFIG_GPIO(GPIOG, 2);
+ CONFIG_GPIO(GPIOG, 3);
+ CONFIG_GPIO(GPIOG, 4);
+ CONFIG_GPIO(GPIOG, 5);
+
+ /* And control lines... */
+ CONFIG_GPIO(GPIOD, 4);
+ CONFIG_GPIO(GPIOD, 5);
+ CONFIG_GPIO(GPIOD, 7);
+ CONFIG_GPIO(GPIOG, 9);
+ CONFIG_GPIO(GPIOG, 10);
+ CONFIG_GPIO(GPIOG, 12);
+ CONFIG_GPIO(GPIOE, 0);
+ CONFIG_GPIO(GPIOE, 1);
+}
+
+#endif /* STM32_HAVE_FSMC */
diff --git a/libmaple/stm32f2-f4/gpio.c b/libmaple/stm32f2-f4/gpio.c
new file mode 100644
index 0000000..a26edaa
--- /dev/null
+++ b/libmaple/stm32f2-f4/gpio.c
@@ -0,0 +1,194 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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/gpio.c
+ * @brief STM32F2 GPIO.
+ */
+
+#include <libmaple/gpio.h>
+#include <libmaple/rcc.h>
+#include <libmaple/bitband.h>
+
+/*
+ * GPIO devices
+ */
+
+gpio_dev gpioa = {
+ .regs = GPIOA_BASE,
+ .clk_id = RCC_GPIOA,
+ .exti_port = EXTI_PA,
+};
+/** GPIO port A device. */
+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;
+
+gpio_dev gpioc = {
+ .regs = GPIOC_BASE,
+ .clk_id = RCC_GPIOC,
+ .exti_port = EXTI_PC,
+};
+/** GPIO port C device. */
+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;
+
+gpio_dev gpioe = {
+ .regs = GPIOE_BASE,
+ .clk_id = RCC_GPIOE,
+ .exti_port = EXTI_PE,
+};
+/** GPIO port E device. */
+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;
+
+gpio_dev gpiog = {
+ .regs = GPIOG_BASE,
+ .clk_id = RCC_GPIOG,
+ .exti_port = EXTI_PG,
+};
+/** GPIO port G device. */
+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;
+
+gpio_dev gpioi = {
+ .regs = GPIOI_BASE,
+ .clk_id = RCC_GPIOI,
+ .exti_port = EXTI_PI,
+};
+/** GPIO port G device. */
+gpio_dev* const GPIOI = &gpioi;
+
+/*
+ * GPIO routines
+ */
+
+/**
+ * Initialize and reset all available GPIO devices.
+ */
+void gpio_init_all(void) {
+ gpio_init(GPIOA);
+ gpio_init(GPIOB);
+ gpio_init(GPIOC);
+ gpio_init(GPIOD);
+ gpio_init(GPIOE);
+ gpio_init(GPIOF);
+ gpio_init(GPIOG);
+ gpio_init(GPIOH);
+ gpio_init(GPIOI);
+}
+
+/**
+ * @brief Set the mode of a GPIO pin.
+ * @param dev GPIO device.
+ * @param bit Bit on dev whose mode to set, 0--15.
+ * @param mode Mode to set the pin to.
+ * @param flags Flags to modify basic mode configuration
+ */
+void gpio_set_modef(gpio_dev *dev,
+ uint8 bit,
+ gpio_pin_mode mode,
+ unsigned flags) {
+ gpio_reg_map *regs = dev->regs;
+ unsigned shift = bit * 2;
+ uint32 tmp;
+
+ /* Mode */
+ tmp = regs->MODER;
+ tmp &= ~(0x3 << shift);
+ tmp |= mode << shift;
+ regs->MODER = tmp;
+
+ /* Output type */
+ bb_peri_set_bit(&regs->OTYPER, bit, flags & 0x1);
+
+ /* Speed */
+ tmp = regs->OSPEEDR;
+ tmp &= ~(0x3 << shift);
+ tmp |= ((flags >> 1) & 0x3) << shift;
+ regs->OSPEEDR = tmp;
+
+ /* Pull-up/pull-down */
+ tmp = regs->PUPDR;
+ tmp &= ~(0x3 << shift);
+ tmp |= ((flags >> 3) & 0x3) << shift;
+ regs->PUPDR = tmp;
+}
+
+/**
+ * @brief Set a pin's alternate function.
+ *
+ * The pin must have its mode set to GPIO_MODE_AF for this to take
+ * effect.
+ *
+ * @param dev Device whose pin to configure.
+ * @param bit Pin whose alternate function to set.
+ * @param af Alternate function to use for pin.
+ * @see gpio_set_modef()
+ */
+void gpio_set_af(gpio_dev *dev, uint8 bit, gpio_af af) {
+ __io uint32 *afr;
+ unsigned shift;
+ uint32 tmp;
+ if (bit >= 8) {
+ afr = &dev->regs->AFRH;
+ shift = 4 * (bit - 8);
+ } else{
+ afr = &dev->regs->AFRL;
+ shift = 4 * bit;
+ }
+ tmp = *afr;
+ tmp &= ~(0xF << shift);
+ tmp |= (af << shift);
+ *afr = tmp;
+}
diff --git a/libmaple/stm32f2-f4/i2c.c b/libmaple/stm32f2-f4/i2c.c
new file mode 100644
index 0000000..42fd427
--- /dev/null
+++ b/libmaple/stm32f2-f4/i2c.c
@@ -0,0 +1,99 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2012 LeafLabs, LLC.
+ * Copyright (c) 2014 Google, Inc.
+ *
+ * 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 "i2c_private.h"
+#include <libmaple/i2c.h>
+
+/*
+ * Devices
+ */
+
+static i2c_dev i2c1 = I2C_DEV_NEW(1, &gpiob, 7, &gpiob, 6);
+static i2c_dev i2c2 = I2C_DEV_NEW(1, &gpioh, 5, &gpioh, 4);
+static i2c_dev i2c3 = I2C_DEV_NEW(1, &gpioh, 8, &gpioh, 7);
+
+/** I2C1 device */
+i2c_dev* const I2C1 = &i2c1;
+/** I2C2 device */
+i2c_dev* const I2C2 = &i2c2;
+/** I2C3 device */
+i2c_dev* const I2C3 = &i2c3;
+
+/*
+ * libmaple routines
+ */
+
+#define I2C_MODEF_FLAGS (GPIO_MODEF_TYPE_OD | GPIO_MODEF_SPEED_HIGH | \
+ GPIO_MODEF_PUPD_PU)
+
+void i2c_config_gpios(const i2c_dev *dev) {
+ /* Untested... */
+ gpio_set_modef(sda_port(dev), dev->sda_pin, GPIO_MODE_AF, I2C_MODEF_FLAGS);
+ gpio_set_modef(scl_port(dev), dev->scl_pin, GPIO_MODE_AF, I2C_MODEF_FLAGS);
+ gpio_set_af(sda_port(dev), dev->sda_pin, GPIO_AF_I2C);
+ gpio_set_af(scl_port(dev), dev->scl_pin, GPIO_AF_I2C);
+}
+
+void i2c_master_release_bus(const i2c_dev *dev) {
+ /* Untested... */
+ unsigned flags = (GPIO_MODEF_TYPE_OD | GPIO_MODEF_SPEED_HIGH |
+ GPIO_MODEF_PUPD_PU);
+ gpio_write_bit(scl_port(dev), dev->scl_pin, 1);
+ gpio_write_bit(sda_port(dev), dev->sda_pin, 1);
+ gpio_set_modef(scl_port(dev), dev->scl_pin, GPIO_MODE_OUTPUT,
+ I2C_MODEF_FLAGS);
+ gpio_set_modef(sda_port(dev), dev->sda_pin, GPIO_MODE_OUTPUT,
+ I2C_MODEF_FLAGS);
+}
+
+/*
+ * IRQ Handlers
+ */
+
+void __irq_i2c1_ev(void) {
+ _i2c_irq_handler(I2C1);
+}
+
+void __irq_i2c2_ev(void) {
+ _i2c_irq_handler(I2C2);
+}
+
+void __irq_i2c3_ev(void) {
+ _i2c_irq_handler(I2C3);
+}
+
+void __irq_i2c1_er(void) {
+ _i2c_irq_error_handler(I2C1);
+}
+
+void __irq_i2c2_er(void) {
+ _i2c_irq_error_handler(I2C2);
+}
+
+void __irq_i2c3_er(void) {
+ _i2c_irq_error_handler(I2C3);
+}
diff --git a/libmaple/stm32f2-f4/include/series/adc.h b/libmaple/stm32f2-f4/include/series/adc.h
new file mode 100644
index 0000000..175fe11
--- /dev/null
+++ b/libmaple/stm32f2-f4/include/series/adc.h
@@ -0,0 +1,335 @@
+/******************************************************************************
+ * 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.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>,
+ * @brief STM32F2 ADC support.
+ */
+
+#ifndef _LIBMAPLE_STM32F2_ADC_H_
+#define _LIBMAPLE_STM32F2_ADC_H_
+
+#include <libmaple/libmaple_types.h>
+
+/*
+ * 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 {
+ /** PCLK2 divided by 2 */
+ ADC_PRE_PCLK2_DIV_2 = ADC_CCR_ADCPRE_PCLK2_DIV_2,
+ /** PCLK2 divided by 4 */
+ ADC_PRE_PCLK2_DIV_4 = ADC_CCR_ADCPRE_PCLK2_DIV_4,
+ /** PCLK2 divided by 6 */
+ ADC_PRE_PCLK2_DIV_6 = ADC_CCR_ADCPRE_PCLK2_DIV_6,
+ /** PCLK2 divided by 8 */
+ ADC_PRE_PCLK2_DIV_8 = ADC_CCR_ADCPRE_PCLK2_DIV_8,
+} adc_prescaler;
+
+#endif
diff --git a/libmaple/stm32f2-f4/include/series/dac.h b/libmaple/stm32f2-f4/include/series/dac.h
new file mode 100644
index 0000000..0a578ca
--- /dev/null
+++ b/libmaple/stm32f2-f4/include/series/dac.h
@@ -0,0 +1,94 @@
+/******************************************************************************
+ * 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/dac.h
+ * @brief STM32F2 DAC support
+ */
+
+#ifndef _LIBMAPLE_STM32F2_DAC_H_
+#define _LIBMAPLE_STM32F2_DAC_H_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include <libmaple/libmaple_types.h>
+
+/*
+ * Register map type
+ */
+
+/** STM32F2 DAC register map type. */
+typedef struct dac_reg_map {
+ __io uint32 CR; /**< Control register */
+ __io uint32 SWTRIGR; /**< Software trigger register */
+ __io uint32 DHR12R1; /**< Channel 1 12-bit right-aligned data
+ holding register */
+ __io uint32 DHR12L1; /**< Channel 1 12-bit left-aligned data
+ holding register */
+ __io uint32 DHR8R1; /**< Channel 1 8-bit left-aligned data
+ holding register */
+ __io uint32 DHR12R2; /**< Channel 2 12-bit right-aligned data
+ holding register */
+ __io uint32 DHR12L2; /**< Channel 2 12-bit left-aligned data
+ holding register */
+ __io uint32 DHR8R2; /**< Channel 2 8-bit left-aligned data
+ holding register */
+ __io uint32 DHR12RD; /**< Dual DAC 12-bit right-aligned data
+ holding register */
+ __io uint32 DHR12LD; /**< Dual DAC 12-bit left-aligned data
+ holding register */
+ __io uint32 DHR8RD; /**< Dual DAC 8-bit right-aligned data holding
+ register */
+ __io uint32 DOR1; /**< Channel 1 data output register */
+ __io uint32 DOR2; /**< Channel 2 data output register */
+ __io uint32 SR; /**< Status register */
+} dac_reg_map;
+
+/*
+ * Register bit definitions
+ */
+
+/* Control register */
+
+#define DAC_CR_DMAUDRIE1 (1U << 13) /* Channel 1 DMA underrun
+ * interrupt enable */
+#define DAC_CR_DMAUDRIE2 (1U << 29) /* Channel 2 DMA underrun
+ * interrupt enable */
+
+/* Status register */
+
+#define DAC_SR_DMAUDR1 (1U << 13) /* Channel 1 DMA underrun
+ * occurred */
+#define DAC_SR_DMAUDR2 (1U << 29) /* Channel 2 DMA underrun
+ * ocurred */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmaple/stm32f2-f4/include/series/dma.h b/libmaple/stm32f2-f4/include/series/dma.h
new file mode 100644
index 0000000..43bd1a2
--- /dev/null
+++ b/libmaple/stm32f2-f4/include/series/dma.h
@@ -0,0 +1,810 @@
+/******************************************************************************
+ * 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/dma.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F2 DMA series header
+ */
+
+#ifndef _LIBMAPLE_STM32F2_DMA_H_
+#define _LIBMAPLE_STM32F2_DMA_H_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include <libmaple/dma_common.h>
+#include <libmaple/libmaple_types.h>
+
+/*
+ * Register map and base pointers
+ */
+
+/**
+ * @brief STM32F2 DMA register map type.
+ */
+typedef struct dma_reg_map {
+ /* Isn't it nice how on F1, it's CCR1, but on F2, it's S1CR? */
+
+ /* Global DMA registers */
+ __io uint32 LISR; /**< Low interrupt status register */
+ __io uint32 HISR; /**< High interrupt status register */
+ __io uint32 LIFCR; /**< Low interrupt flag clear register */
+ __io uint32 HIFCR; /**< High interrupt flag clear register */
+ /* Stream 0 registers */
+ __io uint32 S0CR; /**< Stream 0 control register */
+ __io uint32 S0NDTR; /**< Stream 0 number of data register */
+ __io uint32 S0PAR; /**< Stream 0 peripheral address register */
+ __io uint32 S0M0AR; /**< Stream 0 memory 0 address register */
+ __io uint32 S0M1AR; /**< Stream 0 memory 1 address register */
+ __io uint32 S0FCR; /**< Stream 0 FIFO control register */
+ /* Stream 1 registers */
+ __io uint32 S1CR; /**< Stream 1 control register */
+ __io uint32 S1NDTR; /**< Stream 1 number of data register */
+ __io uint32 S1PAR; /**< Stream 1 peripheral address register */
+ __io uint32 S1M0AR; /**< Stream 1 memory 0 address register */
+ __io uint32 S1M1AR; /**< Stream 1 memory 1 address register */
+ __io uint32 S1FCR; /**< Stream 1 FIFO control register */
+ /* Stream 2 registers */
+ __io uint32 S2CR; /**< Stream 2 control register */
+ __io uint32 S2NDTR; /**< Stream 2 number of data register */
+ __io uint32 S2PAR; /**< Stream 2 peripheral address register */
+ __io uint32 S2M0AR; /**< Stream 2 memory 0 address register */
+ __io uint32 S2M1AR; /**< Stream 2 memory 1 address register */
+ __io uint32 S2FCR; /**< Stream 2 FIFO control register */
+ /* Stream 3 registers */
+ __io uint32 S3CR; /**< Stream 3 control register */
+ __io uint32 S3NDTR; /**< Stream 3 number of data register */
+ __io uint32 S3PAR; /**< Stream 3 peripheral address register */
+ __io uint32 S3M0AR; /**< Stream 3 memory 0 address register */
+ __io uint32 S3M1AR; /**< Stream 3 memory 1 address register */
+ __io uint32 S3FCR; /**< Stream 3 FIFO control register */
+ /* Stream 4 registers */
+ __io uint32 S4CR; /**< Stream 4 control register */
+ __io uint32 S4NDTR; /**< Stream 4 number of data register */
+ __io uint32 S4PAR; /**< Stream 4 peripheral address register */
+ __io uint32 S4M0AR; /**< Stream 4 memory 0 address register */
+ __io uint32 S4M1AR; /**< Stream 4 memory 1 address register */
+ __io uint32 S4FCR; /**< Stream 4 FIFO control register */
+ /* Stream 5 registers */
+ __io uint32 S5CR; /**< Stream 5 control register */
+ __io uint32 S5NDTR; /**< Stream 5 number of data register */
+ __io uint32 S5PAR; /**< Stream 5 peripheral address register */
+ __io uint32 S5M0AR; /**< Stream 5 memory 0 address register */
+ __io uint32 S5M1AR; /**< Stream 5 memory 1 address register */
+ __io uint32 S5FCR; /**< Stream 5 FIFO control register */
+ /* Stream 6 registers */
+ __io uint32 S6CR; /**< Stream 6 control register */
+ __io uint32 S6NDTR; /**< Stream 6 number of data register */
+ __io uint32 S6PAR; /**< Stream 6 peripheral address register */
+ __io uint32 S6M0AR; /**< Stream 6 memory 0 address register */
+ __io uint32 S6M1AR; /**< Stream 6 memory 1 address register */
+ __io uint32 S6FCR; /**< Stream 6 FIFO control register */
+ /* Stream 7 registers */
+ __io uint32 S7CR; /**< Stream 7 control register */
+ __io uint32 S7NDTR; /**< Stream 7 number of data register */
+ __io uint32 S7PAR; /**< Stream 7 peripheral address register */
+ __io uint32 S7M0AR; /**< Stream 7 memory 0 address register */
+ __io uint32 S7M1AR; /**< Stream 7 memory 1 address register */
+ __io uint32 S7FCR; /**< Stream 7 FIFO control register */
+} dma_reg_map;
+
+/** DMA controller 1 register map base pointer */
+#define DMA1_BASE ((struct dma_reg_map*)0x40026000)
+/** DMA controller 2 register map base pointer */
+#define DMA2_BASE ((struct dma_reg_map*)0x40026400)
+
+/**
+ * @brief STM32F2 DMA stream (i.e. tube) register map type.
+ * Provides access to an individual stream's registers.
+ * @see dma_tube_regs()
+ */
+typedef struct dma_tube_reg_map {
+ __io uint32 SCR; /**< Stream configuration register */
+ __io uint32 SNDTR; /**< Stream number of data register */
+ __io uint32 SPAR; /**< Stream peripheral address register */
+ __io uint32 SM0AR; /**< Stream memory 0 address register */
+ __io uint32 SM1AR; /**< Stream memory 1 address register */
+ __io uint32 SFCR; /**< Stream FIFO control register */
+} dma_tube_reg_map;
+
+/** DMA1 stream 0 register map base pointer */
+#define DMA1S0_BASE ((struct dma_tube_reg_map*)0x40026010)
+/** DMA1 stream 1 register map base pointer */
+#define DMA1S1_BASE ((struct dma_tube_reg_map*)0x40026028)
+/** DMA1 stream 2 register map base pointer */
+#define DMA1S2_BASE ((struct dma_tube_reg_map*)0x40026040)
+/** DMA1 stream 3 register map base pointer */
+#define DMA1S3_BASE ((struct dma_tube_reg_map*)0x40026058)
+/** DMA1 stream 4 register map base pointer */
+#define DMA1S4_BASE ((struct dma_tube_reg_map*)0x40026070)
+/** DMA1 stream 5 register map base pointer */
+#define DMA1S5_BASE ((struct dma_tube_reg_map*)0x40026088)
+/** DMA1 stream 6 register map base pointer */
+#define DMA1S6_BASE ((struct dma_tube_reg_map*)0x400260A0)
+/** DMA1 stream 7 register map base pointer */
+#define DMA1S7_BASE ((struct dma_tube_reg_map*)0x400260B8)
+
+/** DMA2 stream 0 register map base pointer */
+#define DMA2S0_BASE ((struct dma_tube_reg_map*)0x40026410)
+/** DMA2 stream 1 register map base pointer */
+#define DMA2S1_BASE ((struct dma_tube_reg_map*)0x40026028)
+/** DMA2 stream 2 register map base pointer */
+#define DMA2S2_BASE ((struct dma_tube_reg_map*)0x40026040)
+/** DMA2 stream 3 register map base pointer */
+#define DMA2S3_BASE ((struct dma_tube_reg_map*)0x40026058)
+/** DMA2 stream 4 register map base pointer */
+#define DMA2S4_BASE ((struct dma_tube_reg_map*)0x40026070)
+/** DMA2 stream 5 register map base pointer */
+#define DMA2S5_BASE ((struct dma_tube_reg_map*)0x40026088)
+/** DMA2 stream 6 register map base pointer */
+#define DMA2S6_BASE ((struct dma_tube_reg_map*)0x400260A0)
+/** DMA2 stream 7 register map base pointer */
+#define DMA2S7_BASE ((struct dma_tube_reg_map*)0x400260B8)
+
+/*
+ * Register bit definitions
+ */
+
+/* Low interrupt status register */
+
+#define DMA_LISR_TCIF3_BIT 27
+#define DMA_LISR_HTIF3_BIT 26
+#define DMA_LISR_TEIF3_BIT 25
+#define DMA_LISR_DMEIF3_BIT 24
+#define DMA_LISR_FEIF3_BIT 22
+#define DMA_LISR_TCIF2_BIT 21
+#define DMA_LISR_HTIF2_BIT 20
+#define DMA_LISR_TEIF2_BIT 19
+#define DMA_LISR_DMEIF2_BIT 18
+#define DMA_LISR_FEIF2_BIT 16
+#define DMA_LISR_TCIF1_BIT 11
+#define DMA_LISR_HTIF1_BIT 10
+#define DMA_LISR_TEIF1_BIT 9
+#define DMA_LISR_DMEIF1_BIT 8
+#define DMA_LISR_FEIF1_BIT 6
+#define DMA_LISR_TCIF0_BIT 5
+#define DMA_LISR_HTIF0_BIT 4
+#define DMA_LISR_TEIF0_BIT 3
+#define DMA_LISR_DMEIF0_BIT 2
+#define DMA_LISR_FEIF0_BIT 0
+
+#define DMA_LISR_TCIF3 (1U << DMA_LISR_TCIF3_BIT)
+#define DMA_LISR_HTIF3 (1U << DMA_LISR_HTIF3_BIT)
+#define DMA_LISR_TEIF3 (1U << DMA_LISR_TEIF3_BIT)
+#define DMA_LISR_DMEIF3 (1U << DMA_LISR_DMEIF3_BIT)
+#define DMA_LISR_FEIF3 (1U << DMA_LISR_FEIF3_BIT)
+#define DMA_LISR_TCIF2 (1U << DMA_LISR_TCIF2_BIT)
+#define DMA_LISR_HTIF2 (1U << DMA_LISR_HTIF2_BIT)
+#define DMA_LISR_TEIF2 (1U << DMA_LISR_TEIF2_BIT)
+#define DMA_LISR_DMEIF2 (1U << DMA_LISR_DMEIF2_BIT)
+#define DMA_LISR_FEIF2 (1U << DMA_LISR_FEIF2_BIT)
+#define DMA_LISR_TCIF1 (1U << DMA_LISR_TCIF1_BIT)
+#define DMA_LISR_HTIF1 (1U << DMA_LISR_HTIF1_BIT)
+#define DMA_LISR_TEIF1 (1U << DMA_LISR_TEIF1_BIT)
+#define DMA_LISR_DMEIF1 (1U << DMA_LISR_DMEIF1_BIT)
+#define DMA_LISR_FEIF1 (1U << DMA_LISR_FEIF1_BIT)
+#define DMA_LISR_TCIF0 (1U << DMA_LISR_TCIF0_BIT)
+#define DMA_LISR_HTIF0 (1U << DMA_LISR_HTIF0_BIT)
+#define DMA_LISR_TEIF0 (1U << DMA_LISR_TEIF0_BIT)
+#define DMA_LISR_DMEIF0 (1U << DMA_LISR_DMEIF0_BIT)
+#define DMA_LISR_FEIF0 (1U << DMA_LISR_FEIF0_BIT)
+
+/* High interrupt status register */
+
+#define DMA_HISR_TCIF7_BIT 27
+#define DMA_HISR_HTIF7_BIT 26
+#define DMA_HISR_TEIF7_BIT 25
+#define DMA_HISR_DMEIF7_BIT 24
+#define DMA_HISR_FEIF7_BIT 22
+#define DMA_HISR_TCIF6_BIT 21
+#define DMA_HISR_HTIF6_BIT 20
+#define DMA_HISR_TEIF6_BIT 19
+#define DMA_HISR_DMEIF6_BIT 18
+#define DMA_HISR_FEIF6_BIT 16
+#define DMA_HISR_TCIF5_BIT 11
+#define DMA_HISR_HTIF5_BIT 10
+#define DMA_HISR_TEIF5_BIT 9
+#define DMA_HISR_DMEIF5_BIT 8
+#define DMA_HISR_FEIF5_BIT 6
+#define DMA_HISR_TCIF4_BIT 5
+#define DMA_HISR_HTIF4_BIT 4
+#define DMA_HISR_TEIF4_BIT 3
+#define DMA_HISR_DMEIF4_BIT 2
+#define DMA_HISR_FEIF4_BIT 0
+
+#define DMA_HISR_TCIF7 (1U << DMA_HISR_TCIF7_BIT)
+#define DMA_HISR_HTIF7 (1U << DMA_HISR_HTIF7_BIT)
+#define DMA_HISR_TEIF7 (1U << DMA_HISR_TEIF7_BIT)
+#define DMA_HISR_DMEIF7 (1U << DMA_HISR_DMEIF7_BIT)
+#define DMA_HISR_FEIF7 (1U << DMA_HISR_FEIF7_BIT)
+#define DMA_HISR_TCIF6 (1U << DMA_HISR_TCIF6_BIT)
+#define DMA_HISR_HTIF6 (1U << DMA_HISR_HTIF6_BIT)
+#define DMA_HISR_TEIF6 (1U << DMA_HISR_TEIF6_BIT)
+#define DMA_HISR_DMEIF6 (1U << DMA_HISR_DMEIF6_BIT)
+#define DMA_HISR_FEIF6 (1U << DMA_HISR_FEIF6_BIT)
+#define DMA_HISR_TCIF5 (1U << DMA_HISR_TCIF5_BIT)
+#define DMA_HISR_HTIF5 (1U << DMA_HISR_HTIF5_BIT)
+#define DMA_HISR_TEIF5 (1U << DMA_HISR_TEIF5_BIT)
+#define DMA_HISR_DMEIF5 (1U << DMA_HISR_DMEIF5_BIT)
+#define DMA_HISR_FEIF5 (1U << DMA_HISR_FEIF5_BIT)
+#define DMA_HISR_TCIF4 (1U << DMA_HISR_TCIF4_BIT)
+#define DMA_HISR_HTIF4 (1U << DMA_HISR_HTIF4_BIT)
+#define DMA_HISR_TEIF4 (1U << DMA_HISR_TEIF4_BIT)
+#define DMA_HISR_DMEIF4 (1U << DMA_HISR_DMEIF4_BIT)
+#define DMA_HISR_FEIF4 (1U << DMA_HISR_FEIF4_BIT)
+
+/* Low interrupt flag clear register */
+
+#define DMA_LIFCR_CTCIF3_BIT 27
+#define DMA_LIFCR_CHTIF3_BIT 26
+#define DMA_LIFCR_CTEIF3_BIT 25
+#define DMA_LIFCR_CDMEIF3_BIT 24
+#define DMA_LIFCR_CFEIF3_BIT 22
+#define DMA_LIFCR_CTCIF2_BIT 21
+#define DMA_LIFCR_CHTIF2_BIT 20
+#define DMA_LIFCR_CTEIF2_BIT 19
+#define DMA_LIFCR_CDMEIF2_BIT 18
+#define DMA_LIFCR_CFEIF2_BIT 16
+#define DMA_LIFCR_CTCIF1_BIT 11
+#define DMA_LIFCR_CHTIF1_BIT 10
+#define DMA_LIFCR_CTEIF1_BIT 9
+#define DMA_LIFCR_CDMEIF1_BIT 8
+#define DMA_LIFCR_CFEIF1_BIT 6
+#define DMA_LIFCR_CTCIF0_BIT 5
+#define DMA_LIFCR_CHTIF0_BIT 4
+#define DMA_LIFCR_CTEIF0_BIT 3
+#define DMA_LIFCR_CDMEIF0_BIT 2
+#define DMA_LIFCR_CFEIF0_BIT 0
+
+#define DMA_LIFCR_CTCIF3 (1U << DMA_LIFCR_CTCIF3_BIT)
+#define DMA_LIFCR_CHTIF3 (1U << DMA_LIFCR_CHTIF3_BIT)
+#define DMA_LIFCR_CTEIF3 (1U << DMA_LIFCR_CTEIF3_BIT)
+#define DMA_LIFCR_CDMEIF3 (1U << DMA_LIFCR_CDMEIF3_BIT)
+#define DMA_LIFCR_CFEIF3 (1U << DMA_LIFCR_CFEIF3_BIT)
+#define DMA_LIFCR_CTCIF2 (1U << DMA_LIFCR_CTCIF2_BIT)
+#define DMA_LIFCR_CHTIF2 (1U << DMA_LIFCR_CHTIF2_BIT)
+#define DMA_LIFCR_CTEIF2 (1U << DMA_LIFCR_CTEIF2_BIT)
+#define DMA_LIFCR_CDMEIF2 (1U << DMA_LIFCR_CDMEIF2_BIT)
+#define DMA_LIFCR_CFEIF2 (1U << DMA_LIFCR_CFEIF2_BIT)
+#define DMA_LIFCR_CTCIF1 (1U << DMA_LIFCR_CTCIF1_BIT)
+#define DMA_LIFCR_CHTIF1 (1U << DMA_LIFCR_CHTIF1_BIT)
+#define DMA_LIFCR_CTEIF1 (1U << DMA_LIFCR_CTEIF1_BIT)
+#define DMA_LIFCR_CDMEIF1 (1U << DMA_LIFCR_CDMEIF1_BIT)
+#define DMA_LIFCR_CFEIF1 (1U << DMA_LIFCR_CFEIF1_BIT)
+#define DMA_LIFCR_CTCIF0 (1U << DMA_LIFCR_CTCIF0_BIT)
+#define DMA_LIFCR_CHTIF0 (1U << DMA_LIFCR_CHTIF0_BIT)
+#define DMA_LIFCR_CTEIF0 (1U << DMA_LIFCR_CTEIF0_BIT)
+#define DMA_LIFCR_CDMEIF0 (1U << DMA_LIFCR_CDMEIF0_BIT)
+#define DMA_LIFCR_CFEIF0 (1U << DMA_LIFCR_CFEIF0_BIT)
+
+/* High interrupt flag clear regsister */
+
+#define DMA_HIFCR_CTCIF7_BIT 27
+#define DMA_HIFCR_CHTIF7_BIT 26
+#define DMA_HIFCR_CTEIF7_BIT 25
+#define DMA_HIFCR_CDMEIF7_BIT 24
+#define DMA_HIFCR_CFEIF7_BIT 22
+#define DMA_HIFCR_CTCIF6_BIT 21
+#define DMA_HIFCR_CHTIF6_BIT 20
+#define DMA_HIFCR_CTEIF6_BIT 19
+#define DMA_HIFCR_CDMEIF6_BIT 18
+#define DMA_HIFCR_CFEIF6_BIT 16
+#define DMA_HIFCR_CTCIF5_BIT 11
+#define DMA_HIFCR_CHTIF5_BIT 10
+#define DMA_HIFCR_CTEIF5_BIT 9
+#define DMA_HIFCR_CDMEIF5_BIT 8
+#define DMA_HIFCR_CFEIF5_BIT 6
+#define DMA_HIFCR_CTCIF4_BIT 5
+#define DMA_HIFCR_CHTIF4_BIT 4
+#define DMA_HIFCR_CTEIF4_BIT 3
+#define DMA_HIFCR_CDMEIF4_BIT 2
+#define DMA_HIFCR_CFEIF4_BIT 0
+
+#define DMA_HIFCR_CTCIF7 (1U << DMA_HIFCR_CTCIF7_BIT)
+#define DMA_HIFCR_CHTIF7 (1U << DMA_HIFCR_CHTIF7_BIT)
+#define DMA_HIFCR_CTEIF7 (1U << DMA_HIFCR_CTEIF7_BIT)
+#define DMA_HIFCR_CDMEIF7 (1U << DMA_HIFCR_CDMEIF7_BIT)
+#define DMA_HIFCR_CFEIF7 (1U << DMA_HIFCR_CFEIF7_BIT)
+#define DMA_HIFCR_CTCIF6 (1U << DMA_HIFCR_CTCIF6_BIT)
+#define DMA_HIFCR_CHTIF6 (1U << DMA_HIFCR_CHTIF6_BIT)
+#define DMA_HIFCR_CTEIF6 (1U << DMA_HIFCR_CTEIF6_BIT)
+#define DMA_HIFCR_CDMEIF6 (1U << DMA_HIFCR_CDMEIF6_BIT)
+#define DMA_HIFCR_CFEIF6 (1U << DMA_HIFCR_CFEIF6_BIT)
+#define DMA_HIFCR_CTCIF5 (1U << DMA_HIFCR_CTCIF5_BIT)
+#define DMA_HIFCR_CHTIF5 (1U << DMA_HIFCR_CHTIF5_BIT)
+#define DMA_HIFCR_CTEIF5 (1U << DMA_HIFCR_CTEIF5_BIT)
+#define DMA_HIFCR_CDMEIF5 (1U << DMA_HIFCR_CDMEIF5_BIT)
+#define DMA_HIFCR_CFEIF5 (1U << DMA_HIFCR_CFEIF5_BIT)
+#define DMA_HIFCR_CTCIF4 (1U << DMA_HIFCR_CTCIF4_BIT)
+#define DMA_HIFCR_CHTIF4 (1U << DMA_HIFCR_CHTIF4_BIT)
+#define DMA_HIFCR_CTEIF4 (1U << DMA_HIFCR_CTEIF4_BIT)
+#define DMA_HIFCR_CDMEIF4 (1U << DMA_HIFCR_CDMEIF4_BIT)
+#define DMA_HIFCR_CFEIF4 (1U << DMA_HIFCR_CFEIF4_BIT)
+
+/* Stream configuration register */
+
+#define DMA_SCR_CT_BIT 19
+#define DMA_SCR_DBM_BIT 18
+#define DMA_SCR_PINCOS_BIT 15
+#define DMA_SCR_MINC_BIT 10
+#define DMA_SCR_PINC_BIT 9
+#define DMA_SCR_CIRC_BIT 8
+#define DMA_SCR_PFCTRL_BIT 5
+#define DMA_SCR_TCIE_BIT 4
+#define DMA_SCR_HTIE_BIT 3
+#define DMA_SCR_TEIE_BIT 2
+#define DMA_SCR_DMEIE_BIT 1
+#define DMA_SCR_EN_BIT 0
+
+#define DMA_SCR_CHSEL (0x7 << 25)
+#define DMA_SCR_CHSEL_CH_0 (0x0 << 25)
+#define DMA_SCR_CHSEL_CH_1 (0x1 << 25)
+#define DMA_SCR_CHSEL_CH_2 (0x2 << 25)
+#define DMA_SCR_CHSEL_CH_3 (0x3 << 25)
+#define DMA_SCR_CHSEL_CH_4 (0x4 << 25)
+#define DMA_SCR_CHSEL_CH_5 (0x5 << 25)
+#define DMA_SCR_CHSEL_CH_6 (0x6 << 25)
+#define DMA_SCR_CHSEL_CH_7 (0x7 << 25)
+#define DMA_SCR_MBURST (0x3 << 23)
+#define DMA_SCR_MBURST_SINGLE (0x0 << 23)
+#define DMA_SCR_MBURST_INCR4 (0x1 << 23)
+#define DMA_SCR_MBURST_INCR8 (0x2 << 23)
+#define DMA_SCR_MBURST_INCR16 (0x3 << 23)
+#define DMA_SCR_PBURST (0x3 << 21)
+#define DMA_SCR_PBURST_SINGLE (0x0 << 21)
+#define DMA_SCR_PBURST_INCR4 (0x1 << 21)
+#define DMA_SCR_PBURST_INCR8 (0x2 << 21)
+#define DMA_SCR_PBURST_INCR16 (0x3 << 21)
+#define DMA_SCR_CT (1U << DMA_SCR_CT_BIT)
+#define DMA_SCR_DBM (1U << DMA_SCR_DBM_BIT)
+#define DMA_SCR_PL (0x3 << 16)
+#define DMA_SCR_PL_LOW (0x0 << 16)
+#define DMA_SCR_PL_MEDIUM (0x1 << 16)
+#define DMA_SCR_PL_HIGH (0x2 << 16)
+#define DMA_SCR_VERY_HIGH (0x3 << 16)
+#define DMA_SCR_PINCOS (1U << DMA_SCR_PINCOS_BIT)
+#define DMA_SCR_MSIZE (0x3 << 13)
+#define DMA_SCR_MSIZE_8BITS (0x0 << 13)
+#define DMA_SCR_MSIZE_16BITS (0x1 << 13)
+#define DMA_SCR_MSIZE_32BITS (0x2 << 13)
+#define DMA_SCR_PSIZE (0x3 << 11)
+#define DMA_SCR_PSIZE_8BITS (0x0 << 11)
+#define DMA_SCR_PSIZE_16BITS (0x1 << 11)
+#define DMA_SCR_PSIZE_32BITS (0x2 << 11)
+#define DMA_SCR_MINC (1U << DMA_SCR_MINC_BIT)
+#define DMA_SCR_PINC (1U << DMA_SCR_PINC_BIT)
+#define DMA_SCR_CIRC (1U << DMA_SCR_CIRC_BIT)
+#define DMA_SCR_DIR (0x3 << 6)
+#define DMA_SCR_DIR_PER_TO_MEM (0x0 << 6)
+#define DMA_SCR_DIR_MEM_TO_PER (0x1 << 6)
+#define DMA_SCR_DIR_MEM_TO_MEM (0x2 << 6)
+#define DMA_SCR_PFCTRL (1U << DMA_SCR_PFCTRL_BIT)
+#define DMA_SCR_TCIE (1U << DMA_SCR_TCIE_BIT)
+#define DMA_SCR_HTIE (1U << DMA_SCR_HTIE_BIT)
+#define DMA_SCR_TEIE (1U << DMA_SCR_TEIE_BIT)
+#define DMA_SCR_DMEIE (1U << DMA_SCR_DMEIE_BIT)
+#define DMA_SCR_EN (1U << DMA_SCR_EN_BIT)
+
+/* Stream FIFO control register */
+
+#define DMA_SFCR_FEIE_BIT 7
+#define DMA_SFCR_DMDIS_BIT 2
+
+#define DMA_SFCR_FEIE (1U << DMA_SFCR_FEIE_BIT)
+#define DMA_SFCR_FS (0x7 << 3)
+#define DMA_SFCR_FS_ZERO_TO_QUARTER (0x0 << 3)
+#define DMA_SFCR_FS_QUARTER_TO_HALF (0x1 << 3)
+#define DMA_SFCR_FS_HALF_TO_THREE_QUARTERS (0x2 << 3)
+#define DMA_SFCR_FS_THREE_QUARTERS_TO_FULL (0x3 << 3)
+#define DMA_SFCR_FS_EMPTY (0x4 << 3)
+#define DMA_SFCR_FS_FULL (0x5 << 3)
+#define DMA_SFCR_DMDIS (1U << DMA_SFCR_DMDIS_BIT)
+#define DMA_SFCR_FTH (0x3 << 0)
+#define DMA_SFCR_FTH_QUARTER_FULL (0x0 << 3)
+#define DMA_SFCR_FTH_HALF_FULL (0x1 << 3)
+#define DMA_SFCR_FTH_THREE_QUARTERS_FULL (0x2 << 3)
+#define DMA_SFCR_FTH_FULL (0x3 << 3)
+
+/*
+ * Devices
+ */
+
+extern dma_dev *DMA1;
+extern dma_dev *DMA2;
+
+/*
+ * Other types needed by, or useful for, <libmaple/dma.h>
+ */
+
+/**
+ * @brief DMA streams
+ * This is also the dma_tube type for STM32F2.
+ * @see dma_tube
+ */
+typedef enum dma_stream {
+ DMA_S0 = 0,
+ DMA_S1 = 1,
+ DMA_S2 = 2,
+ DMA_S3 = 3,
+ DMA_S4 = 4,
+ DMA_S5 = 5,
+ DMA_S6 = 6,
+ DMA_S7 = 7,
+} dma_stream;
+
+/** STM32F2 dma_tube (=dma_stream) */
+#define dma_tube dma_stream
+
+/**
+ * @brief STM32F2 configuration flags for dma_tube_config.
+ * @see struct dma_tube_config
+ */
+typedef enum dma_cfg_flags {
+ /* NB: flags that aren't SCR bits are treated specially. */
+
+ /**
+ * Source address increment mode
+ *
+ * If this flag is set, the source address is incremented (by the
+ * source size) after each DMA transfer.
+ */
+ DMA_CFG_SRC_INC = 1U << 31,
+
+ /**
+ * Destination address increment mode
+ *
+ * If this flag is set, the destination address is incremented (by
+ * the destination size) after each DMA transfer.
+ */
+ DMA_CFG_DST_INC = 1U << 30,
+
+ /**
+ * Circular mode
+ *
+ * This mode is not available for memory-to-memory transfers.
+ */
+ DMA_CFG_CIRC = DMA_SCR_CIRC,
+
+ /** Transfer complete interrupt enable */
+ DMA_CFG_CMPLT_IE = DMA_SCR_TCIE,
+ /** Transfer half-complete interrupt enable */
+ DMA_CFG_HALF_CMPLT_IE = DMA_SCR_HTIE,
+ /** Transfer error interrupt enable */
+ DMA_CFG_ERR_IE = DMA_SCR_TEIE,
+ /** Direct mode error interrupt enable */
+ DMA_CFG_DM_ERR_IE = DMA_SCR_DMEIE,
+ /** FIFO error interrupt enable */
+ DMA_CFG_FIFO_ERR_IE = (1U << 29),
+} dma_cfg_flags;
+
+/**
+ * @brief STM32F2 DMA request sources.
+ *
+ * IMPORTANT:
+ *
+ * 1. On STM32F2, a particular dma_request_src is always tied to a
+ * single DMA controller, but often can be supported by multiple
+ * streams. For example, DMA requests from ADC1 (DMA_REQ_SRC_ADC1) can
+ * only be handled by DMA2, but they can go to either stream 0 or
+ * stream 4 (though not any other stream). If you try to use a request
+ * source with the wrong DMA controller or the wrong stream on
+ * STM32F2, dma_tube_cfg() will fail.
+ *
+ * 2. A single stream can only handle a single request source at a
+ * time. If you change a stream's request source later, it will stop
+ * serving requests from the old source. However, for some streams,
+ * some sources conflict with one another (when they correspond to the
+ * same channel on that stream), and on STM32F2, Terrible Super-Bad
+ * Things will happen if two conflicting request sources are active at
+ * the same time.
+ *
+ * @see struct dma_tube_config
+ * @see dma_tube_cfg()
+ */
+typedef enum dma_request_src {
+ /* These are constructed like so (though this may change, so user
+ * code shouldn't depend on it):
+ *
+ * Bits 0--2: Channel associated with request source
+ *
+ * Bits 3--9: rcc_clk_id of DMA controller associated with request source
+ *
+ * Bits 10--17: Bit mask of streams which can handle that request
+ * source. (E.g., bit 10 set means stream 0 can
+ * handle the source, bit 11 set means stream 1 can,
+ * etc.)
+ *
+ * Among other things, this is used for error checking in
+ * dma_tube_cfg(). If you change this bit encoding, you need to
+ * update the helper functions in stm32f2/dma.c.
+ */
+#define _DMA_STM32F2_REQ_SRC(stream_mask, clk_id, channel) \
+ (((stream_mask) << 10) | ((clk_id) << 3) | (channel))
+#define _DMA_S(n) (1U << (n))
+
+ /* DMA1 request sources */
+#define _DMA_1_REQ_SRC(stream_mask, channel) \
+ _DMA_STM32F2_REQ_SRC(stream_mask, RCC_DMA1, channel)
+
+ /* Channel 0 */
+ DMA_REQ_SRC_SPI3_RX = _DMA_1_REQ_SRC(_DMA_S(0) | _DMA_S(2), 0),
+ DMA_REQ_SRC_SPI2_RX = _DMA_1_REQ_SRC(_DMA_S(3), 0),
+ DMA_REQ_SRC_SPI2_TX = _DMA_1_REQ_SRC(_DMA_S(4), 0),
+ DMA_REQ_SRC_SPI3_TX = _DMA_1_REQ_SRC(_DMA_S(5) | _DMA_S(7), 0),
+
+ /* Channel 1 */
+ DMA_REQ_SRC_I2C1_RX = _DMA_1_REQ_SRC(_DMA_S(0) | _DMA_S(5), 1),
+ DMA_REQ_SRC_TIM7_UP = _DMA_1_REQ_SRC(_DMA_S(2) | _DMA_S(4), 1),
+ DMA_REQ_SRC_I2C1_TX = _DMA_1_REQ_SRC(_DMA_S(6) | _DMA_S(7), 1),
+
+ /* Channel 2 */
+ DMA_REQ_SRC_TIM4_CH1 = _DMA_1_REQ_SRC(_DMA_S(0), 2),
+ DMA_REQ_SRC_TIM4_CH2 = _DMA_1_REQ_SRC(_DMA_S(3), 2),
+ DMA_REQ_SRC_TIM4_UP = _DMA_1_REQ_SRC(_DMA_S(6), 2),
+ DMA_REQ_SRC_TIM4_CH3 = _DMA_1_REQ_SRC(_DMA_S(7), 2),
+
+ /* Channel 3 */
+ DMA_REQ_SRC_TIM2_UP = _DMA_1_REQ_SRC(_DMA_S(1) | _DMA_S(7), 3),
+ DMA_REQ_SRC_TIM2_CH3 = _DMA_1_REQ_SRC(_DMA_S(1), 3),
+ DMA_REQ_SRC_I2C3_RX = _DMA_1_REQ_SRC(_DMA_S(2), 3),
+ DMA_REQ_SRC_I2C3_TX = _DMA_1_REQ_SRC(_DMA_S(4), 3),
+ DMA_REQ_SRC_TIM2_CH1 = _DMA_1_REQ_SRC(_DMA_S(5), 3),
+ DMA_REQ_SRC_TIM2_CH2 = _DMA_1_REQ_SRC(_DMA_S(6), 3),
+ DMA_REQ_SRC_TIM2_CH4 = _DMA_1_REQ_SRC(_DMA_S(6) | _DMA_S(7), 3),
+
+ /* Channel 4 */
+ DMA_REQ_SRC_UART5_RX = _DMA_1_REQ_SRC(_DMA_S(0), 4),
+ DMA_REQ_SRC_USART3_RX = _DMA_1_REQ_SRC(_DMA_S(1), 4),
+ DMA_REQ_SRC_UART4_RX = _DMA_1_REQ_SRC(_DMA_S(2), 4),
+ DMA_REQ_SRC_USART3_TX = _DMA_1_REQ_SRC(_DMA_S(3), 4),
+ DMA_REQ_SRC_UART4_TX = _DMA_1_REQ_SRC(_DMA_S(4), 4),
+ DMA_REQ_SRC_USART2_RX = _DMA_1_REQ_SRC(_DMA_S(5), 4),
+ DMA_REQ_SRC_USART2_TX = _DMA_1_REQ_SRC(_DMA_S(6), 4),
+ DMA_REQ_SRC_UART5_TX = _DMA_1_REQ_SRC(_DMA_S(7), 4),
+
+ /* Channel 5 */
+ DMA_REQ_SRC_TIM3_CH4 = _DMA_1_REQ_SRC(_DMA_S(2), 5),
+ DMA_REQ_SRC_TIM3_UP = _DMA_1_REQ_SRC(_DMA_S(2), 5),
+ DMA_REQ_SRC_TIM3_CH1 = _DMA_1_REQ_SRC(_DMA_S(4), 5),
+ DMA_REQ_SRC_TIM3_TRIG = _DMA_1_REQ_SRC(_DMA_S(4), 5),
+ DMA_REQ_SRC_TIM3_CH2 = _DMA_1_REQ_SRC(_DMA_S(5), 5),
+ DMA_REQ_SRC_TIM3_CH3 = _DMA_1_REQ_SRC(_DMA_S(7), 5),
+
+ /* Channel 6 */
+ DMA_REQ_SRC_TIM5_CH3 = _DMA_1_REQ_SRC(_DMA_S(0), 6),
+ DMA_REQ_SRC_TIM5_UP = _DMA_1_REQ_SRC(_DMA_S(0) | _DMA_S(6), 6),
+ DMA_REQ_SRC_TIM5_CH4 = _DMA_1_REQ_SRC(_DMA_S(1) | _DMA_S(3), 6),
+ DMA_REQ_SRC_TIM5_TRIG = _DMA_1_REQ_SRC(_DMA_S(1) | _DMA_S(3), 6),
+ DMA_REQ_SRC_TIM5_CH1 = _DMA_1_REQ_SRC(_DMA_S(2), 6),
+ DMA_REQ_SRC_TIM5_CH2 = _DMA_1_REQ_SRC(_DMA_S(4), 6),
+
+ /* Channel 7 */
+ DMA_REQ_SRC_TIM6_UP = _DMA_1_REQ_SRC(_DMA_S(1), 7),
+ DMA_REQ_SRC_I2C2_RX = _DMA_1_REQ_SRC(_DMA_S(2) | _DMA_S(3), 7),
+ DMA_REQ_SRC_USART3_TX_ALTERNATE = _DMA_1_REQ_SRC(_DMA_S(4), 7),
+ DMA_REQ_SRC_DAC1 = _DMA_1_REQ_SRC(_DMA_S(5), 7),
+ DMA_REQ_SRC_DAC2 = _DMA_1_REQ_SRC(_DMA_S(6), 7),
+ DMA_REQ_SRC_I2C2_TX = _DMA_1_REQ_SRC(_DMA_S(7), 7),
+#undef _DMA_1_REQ_SRC
+
+ /* DMA2 request sources */
+#define _DMA_2_REQ_SRC(stream_mask, channel) \
+ _DMA_STM32F2_REQ_SRC(stream_mask, RCC_DMA2, channel)
+
+ /* Channel 0 */
+ DMA_REQ_SRC_ADC1 = _DMA_2_REQ_SRC(_DMA_S(0) | _DMA_S(4), 0),
+ /* You can use these "DMA_REQ_SRC_TIMx_CHx_ALTERNATE" if you know
+ * what you're doing, but the other ones (for channels 6 and 7),
+ * are better, in that they don't conflict with one another. */
+ DMA_REQ_SRC_TIM8_CH1_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(2), 0),
+ DMA_REQ_SRC_TIM8_CH2_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(2), 0),
+ DMA_REQ_SRC_TIM8_CH3_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(2), 0),
+ DMA_REQ_SRC_TIM1_CH1_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(6), 0),
+ DMA_REQ_SRC_TIM1_CH2_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(6), 0),
+ DMA_REQ_SRC_TIM1_CH3_ALTENRATE = _DMA_2_REQ_SRC(_DMA_S(6), 0),
+
+ /* Channel 1 */
+ DMA_REQ_SRC_DCMI = _DMA_2_REQ_SRC(_DMA_S(1) | _DMA_S(7), 1),
+ DMA_REQ_SRC_ADC2 = _DMA_2_REQ_SRC(_DMA_S(2) | _DMA_S(3), 1),
+
+ /* Channel 2 */
+ DMA_REQ_SRC_ADC3 = _DMA_2_REQ_SRC(_DMA_S(0) | _DMA_S(1), 2),
+ DMA_REQ_SRC_CRYP_OUT = _DMA_2_REQ_SRC(_DMA_S(5), 2),
+ DMA_REQ_SRC_CRYP_IN = _DMA_2_REQ_SRC(_DMA_S(6), 2),
+ DMA_REQ_SRC_HASH_IN = _DMA_2_REQ_SRC(_DMA_S(7), 2),
+
+ /* Channel 3 */
+ DMA_REQ_SRC_SPI1_RX = _DMA_2_REQ_SRC(_DMA_S(0) | _DMA_S(2), 3),
+ DMA_REQ_SRC_SPI1_TX = _DMA_2_REQ_SRC(_DMA_S(3) | _DMA_S(5), 3),
+
+ /* Channel 4 */
+ DMA_REQ_SRC_USART1_RX = _DMA_2_REQ_SRC(_DMA_S(2) | _DMA_S(5), 4),
+ DMA_REQ_SRC_SDIO = _DMA_2_REQ_SRC(_DMA_S(3) | _DMA_S(6), 4),
+ DMA_REQ_SRC_USART1_TX = _DMA_2_REQ_SRC(_DMA_S(7), 4),
+
+ /* Channel 5 */
+ DMA_REQ_SRC_USART6_RX = _DMA_2_REQ_SRC(_DMA_S(1) | _DMA_S(2), 5),
+ DMA_REQ_SRC_USART6_TX = _DMA_2_REQ_SRC(_DMA_S(6) | _DMA_S(7), 5),
+
+ /* Channel 6 */
+ DMA_REQ_SRC_TIM1_TRIG = _DMA_2_REQ_SRC(_DMA_S(0) | _DMA_S(4), 6),
+ DMA_REQ_SRC_TIM1_CH1 = _DMA_2_REQ_SRC(_DMA_S(1) | _DMA_S(3), 6),
+ DMA_REQ_SRC_TIM1_CH2 = _DMA_2_REQ_SRC(_DMA_S(3), 6),
+ DMA_REQ_SRC_TIM1_CH4 = _DMA_2_REQ_SRC(_DMA_S(4), 6),
+ DMA_REQ_SRC_TIM1_COM = _DMA_2_REQ_SRC(_DMA_S(4), 6),
+ DMA_REQ_SRC_TIM1_UP = _DMA_2_REQ_SRC(_DMA_S(5), 6),
+ DMA_REQ_SRC_TIM1_CH3 = _DMA_2_REQ_SRC(_DMA_S(6), 6),
+
+ /* Channel 7 */
+ DMA_REQ_SRC_TIM8_UP = _DMA_2_REQ_SRC(_DMA_S(1), 7),
+ DMA_REQ_SRC_TIM8_CH1 = _DMA_2_REQ_SRC(_DMA_S(2), 7),
+ DMA_REQ_SRC_TIM8_CH2 = _DMA_2_REQ_SRC(_DMA_S(3), 7),
+ DMA_REQ_SRC_TIM8_CH3 = _DMA_2_REQ_SRC(_DMA_S(4), 7),
+ DMA_REQ_SRC_TIM8_CH4 = _DMA_2_REQ_SRC(_DMA_S(7), 7),
+ DMA_REQ_SRC_TIM8_TRIG = _DMA_2_REQ_SRC(_DMA_S(7), 7),
+ DMA_REQ_SRC_TIM8_COM = _DMA_2_REQ_SRC(_DMA_S(7), 7),
+#undef _DMA_2_REQ_SRC
+#undef _DMA_S
+} dma_request_src;
+
+/*
+ * Tube conveniences
+ */
+
+static inline dma_tube_reg_map* dma_tube_regs(dma_dev *dev,
+ dma_tube tube) {
+ ASSERT(DMA_S0 <= tube && tube <= DMA_S7);
+ switch (dev->clk_id) {
+ case RCC_DMA1:
+ return DMA1S0_BASE + (int)tube;
+ case RCC_DMA2:
+ return DMA2S0_BASE + (int)tube;
+ default:
+ /* Can't happen */
+ ASSERT(0);
+ return 0;
+ }
+}
+
+static inline uint8 dma_is_enabled(dma_dev *dev, dma_tube tube) {
+ return dma_tube_regs(dev, tube)->SCR & DMA_SCR_EN;
+}
+
+/* F2-only; available because of double-buffering. */
+void dma_set_mem_n_addr(dma_dev *dev, dma_tube tube, int n,
+ __io void *address);
+
+/**
+ * @brief Set memory 0 address.
+ * Availability: STM32F2.
+ *
+ * @param dev DMA device
+ * @param tube Tube whose memory 0 address to set
+ * @param addr Address to use as memory 0
+ */
+static __always_inline void
+dma_set_mem0_addr(dma_dev *dev, dma_tube tube, __io void *addr) {
+ dma_set_mem_n_addr(dev, tube, 0, addr);
+}
+
+/**
+ * @brief Set memory 1 address.
+ * Availability: STM32F2.
+ *
+ * @param dev DMA device
+ * @param tube Tube whose memory 1 address to set
+ * @param addr Address to use as memory 1
+ */
+static __always_inline void
+dma_set_mem1_addr(dma_dev *dev, dma_tube tube, __io void *addr) {
+ dma_set_mem_n_addr(dev, tube, 1, addr);
+}
+
+/* Assume the user means SM0AR in a non-double-buffered configuration. */
+static __always_inline void
+dma_set_mem_addr(dma_dev *dev, dma_tube tube, __io void *addr) {
+ dma_set_mem0_addr(dev, tube, addr);
+}
+
+/* SM0AR and SM1AR are treated as though they have the same size */
+static inline dma_xfer_size dma_get_mem_size(dma_dev *dev, dma_tube tube) {
+ return (dma_xfer_size)(dma_tube_regs(dev, tube)->SCR >> 13);
+}
+
+static inline dma_xfer_size dma_get_per_size(dma_dev *dev, dma_tube tube) {
+ return (dma_xfer_size)(dma_tube_regs(dev, tube)->SCR >> 11);
+}
+
+void dma_enable_fifo(dma_dev *dev, dma_tube tube);
+void dma_disable_fifo(dma_dev *dev, dma_tube tube);
+
+static __always_inline int dma_is_fifo_enabled(dma_dev *dev, dma_tube tube) {
+ return dma_tube_regs(dev, tube)->SFCR & DMA_SFCR_DMDIS;
+}
+
+/*
+ * TODO:
+ * - Double-buffer configuration function
+ * - FIFO configuration function
+ * - MBURST/PBURST configuration function
+ */
+
+/*
+ * ISR/IFCR conveniences.
+ */
+
+/* (undocumented) helper for reading LISR/HISR and writing
+ * LIFCR/HIFCR. For these registers,
+ *
+ * S0, S4: bits start at bit 0
+ * S1, S5: 6
+ * S2, S6: 16
+ * S3, S7: 22
+ *
+ * I can't imagine why ST didn't just use a byte for each group. The
+ * bits fit, and it would have made functions like these simpler and
+ * faster. Oh well. */
+static __always_inline uint32 _dma_sr_fcr_shift(dma_tube tube) {
+ switch (tube) {
+ case DMA_S0: /* fall through */
+ case DMA_S4:
+ return 0;
+ case DMA_S1: /* fall through */
+ case DMA_S5:
+ return 6;
+ case DMA_S2: /* fall through */
+ case DMA_S6:
+ return 16;
+ case DMA_S3: /* fall through */
+ case DMA_S7:
+ return 22;
+ }
+ /* Can't happen */
+ ASSERT(0);
+ return 0;
+}
+
+static inline uint8 dma_get_isr_bits(dma_dev *dev, dma_tube tube) {
+ dma_reg_map *regs = dev->regs;
+ __io uint32 *isr = tube > DMA_S3 ? &regs->HISR : &regs->LISR;
+ return (*isr >> _dma_sr_fcr_shift(tube)) & 0x3D;
+}
+
+static inline void dma_clear_isr_bits(dma_dev *dev, dma_tube tube) {
+ dma_reg_map *regs = dev->regs;
+ __io uint32 *ifcr = tube > DMA_S3 ? &regs->HIFCR : &regs->LIFCR;
+ *ifcr = (0x3D << _dma_sr_fcr_shift(tube));
+}
+
+#undef _DMA_IRQ_BIT_SHIFT
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif
diff --git a/libmaple/stm32f2-f4/include/series/exti.h b/libmaple/stm32f2-f4/include/series/exti.h
new file mode 100644
index 0000000..4643fcf
--- /dev/null
+++ b/libmaple/stm32f2-f4/include/series/exti.h
@@ -0,0 +1,46 @@
+/******************************************************************************
+ * 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/stm32f1/include/series/exti.h
+ * @brief STM32F2 external interrupts
+ */
+
+#ifndef _LIBMAPLE_STM32F2_EXTI_H_
+#define _LIBMAPLE_STM32F2_EXTI_H_
+
+#ifdef __cpluspus
+extern "C" {
+#endif
+
+struct exti_reg_map;
+#define EXTI_BASE ((struct exti_reg_map*)0x40013C00)
+
+#ifdef __cpluspus
+}
+#endif
+
+#endif
diff --git a/libmaple/stm32f2-f4/include/series/flash.h b/libmaple/stm32f2-f4/include/series/flash.h
new file mode 100644
index 0000000..1da55cd
--- /dev/null
+++ b/libmaple/stm32f2-f4/include/series/flash.h
@@ -0,0 +1,206 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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/flash.h
+ * @brief STM32F2 Flash header.
+ *
+ * Provides register map, base pointer, and register bit definitions
+ * for the Flash controller on the STM32F2 series, along with
+ * series-specific configuration values.
+ */
+
+#ifndef _LIBMAPLE_STM32F2_FLASH_H_
+#define _LIBMAPLE_STM32F2_FLASH_H_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include <libmaple/libmaple_types.h>
+
+/*
+ * Register map
+ */
+
+/** @brief STM32F2 Flash register map type */
+typedef struct flash_reg_map {
+ __io uint32 ACR; /**< Access control register */
+ __io uint32 KEYR; /**< Key register */
+ __io uint32 OPTKEYR; /**< Option key register */
+ __io uint32 SR; /**< Status register */
+ __io uint32 CR; /**< Control register */
+ __io uint32 OPTCR; /**< Option control register */
+} flash_reg_map;
+
+#define FLASH_BASE ((struct flash_reg_map*)0x40023C00)
+
+/*
+ * Register bit definitions
+ */
+
+/* Access control register */
+
+#define FLASH_ACR_DCRST_BIT 12
+#define FLASH_ACR_ICRST_BIT 11
+#define FLASH_ACR_DCEN_BIT 10
+#define FLASH_ACR_ICEN_BIT 9
+#define FLASH_ACR_PRFTEN_BIT 8
+
+#define FLASH_ACR_DCRST (1U << FLASH_ACR_DCRST_BIT)
+#define FLASH_ACR_ICRST (1U << FLASH_ACR_ICRST_BIT)
+#define FLASH_ACR_DCEN (1U << FLASH_ACR_DCEN_BIT)
+#define FLASH_ACR_ICEN (1U << FLASH_ACR_ICEN_BIT)
+#define FLASH_ACR_PRFTEN (1U << FLASH_ACR_PRFTEN_BIT)
+#define FLASH_ACR_LATENCY 0x7
+#define FLASH_ACR_LATENCY_0WS 0x0
+#define FLASH_ACR_LATENCY_1WS 0x1
+#define FLASH_ACR_LATENCY_2WS 0x2
+#define FLASH_ACR_LATENCY_3WS 0x3
+#define FLASH_ACR_LATENCY_4WS 0x4
+#define FLASH_ACR_LATENCY_5WS 0x5
+#define FLASH_ACR_LATENCY_6WS 0x6
+#define FLASH_ACR_LATENCY_7WS 0x7
+
+/* Key register */
+
+#define FLASH_KEYR_KEY1 0x45670123
+#define FLASH_KEYR_KEY2 0xCDEF89AB
+
+/* Option key register */
+
+#define FLASH_OPTKEYR_OPTKEY1 0x08192A3B
+#define FLASH_OPTKEYR_OPTKEY2 0x4C5D6E7F
+
+/* Status register */
+
+#define FLASH_SR_BSY_BIT 16
+#define FLASH_SR_PGSERR_BIT 7
+#define FLASH_SR_PGPERR_BIT 6
+#define FLASH_SR_PGAERR_BIT 5
+#define FLASH_SR_WRPERR_BIT 4
+#define FLASH_SR_OPERR_BIT 1
+#define FLASH_SR_EOP_BIT 0
+
+#define FLASH_SR_BSY (1U << FLASH_SR_BSY_BIT)
+#define FLASH_SR_PGSERR (1U << FLASH_SR_PGSERR_BIT)
+#define FLASH_SR_PGPERR (1U << FLASH_SR_PGPERR_BIT)
+#define FLASH_SR_PGAERR (1U << FLASH_SR_PGAERR_BIT)
+#define FLASH_SR_WRPERR (1U << FLASH_SR_WRPERR_BIT)
+#define FLASH_SR_OPERR (1U << FLASH_SR_OPERR_BIT)
+#define FLASH_SR_EOP (1U << FLASH_SR_EOP_BIT)
+
+/* Control register */
+
+#define FLASH_CR_LOCK_BIT 31
+#define FLASH_CR_ERRIE_BIT 25
+#define FLASH_CR_EOPIE_BIT 24
+#define FLASH_CR_STRT_BIT 16
+#define FLASH_CR_MER_BIT 2
+#define FLASH_CR_SER_BIT 1
+#define FLASH_CR_PG_BIT 0
+
+#define FLASH_CR_LOCK (1U << FLASH_CR_LOCK_BIT)
+#define FLASH_CR_ERRIE (1U << FLASH_CR_ERRIE_BIT)
+#define FLASH_CR_EOPIE (1U << FLASH_CR_EOPIE_BIT)
+#define FLASH_CR_STRT (1U << FLASH_CR_STRT_BIT)
+
+#define FLASH_CR_PSIZE (0x3 << 8)
+#define FLASH_CR_PSIZE_MUL8 (0x0 << 8)
+#define FLASH_CR_PSIZE_MUL16 (0x1 << 8)
+#define FLASH_CR_PSIZE_MUL32 (0x2 << 8)
+#define FLASH_CR_PSIZE_MUL64 (0x3 << 8)
+
+#define FLASH_CR_SNB (0xF << 3)
+#define FLASH_CR_SNB_0 (0x0 << 3)
+#define FLASH_CR_SNB_1 (0x1 << 3)
+#define FLASH_CR_SNB_2 (0x2 << 3)
+#define FLASH_CR_SNB_3 (0x3 << 3)
+#define FLASH_CR_SNB_4 (0x4 << 3)
+#define FLASH_CR_SNB_5 (0x5 << 3)
+#define FLASH_CR_SNB_6 (0x6 << 3)
+#define FLASH_CR_SNB_7 (0x7 << 3)
+#define FLASH_CR_SNB_8 (0x8 << 3)
+#define FLASH_CR_SNB_9 (0x9 << 3)
+#define FLASH_CR_SNB_10 (0xA << 3)
+#define FLASH_CR_SNB_11 (0xB << 3)
+
+#define FLASH_CR_MER (1U << FLASH_CR_MER_BIT)
+#define FLASH_CR_SER (1U << FLASH_CR_SER_BIT)
+#define FLASH_CR_PG (1U << FLASH_CR_PG_BIT)
+
+/* Option control register */
+
+#define FLASH_OPTCR_NRST_STDBY_BIT 7
+#define FLASH_OPTCR_NRST_STOP_BIT 6
+#define FLASH_OPTCR_WDG_SW_BIT 5
+#define FLASH_OPTCR_OPTSTRT_BIT 1
+#define FLASH_OPTCR_OPTLOCK_BIT 0
+
+#define FLASH_OPTCR_NWRP (0x3FF << 16)
+
+/* Excluded: The many level 1 values */
+#define FLASH_OPTCR_RDP (0xFF << 8)
+#define FLASH_OPTCR_RDP_LEVEL0 (0xAA << 8)
+#define FLASH_OPTCR_RDP_LEVEL2 (0xCC << 8)
+
+#define FLASH_OPTCR_USER (0x7 << 5)
+#define FLASH_OPTCR_nRST_STDBY (1U << FLASH_OPTCR_nRST_STDBY_BIT)
+#define FLASH_OPTCR_nRST_STOP (1U << FLASH_OPTCR_nRST_STOP_BIT)
+#define FLASH_OPTCR_WDG_SW (1U << FLASH_OPTCR_WDG_SW_BIT)
+
+#define FLASH_OPTCR_BOR_LEV (0x3 << 2)
+#define FLASH_OPTCR_BOR_LEVEL3 (0x0 << 2)
+#define FLASH_OPTCR_BOR_LEVEL2 (0x1 << 2)
+#define FLASH_OPTCR_BOR_LEVEL1 (0x2 << 2)
+#define FLASH_OPTCR_BOR_OFF (0x3 << 2)
+
+#define FLASH_OPTCR_OPTSTRT (1U << FLASH_OPTCR_OPTSTRT_BIT)
+#define FLASH_OPTCR_OPTLOCK (1U << FLASH_OPTCR_OPTLOCK_BIT)
+
+/*
+ * Series-specific configuration values
+ */
+
+/* Note that this value depends on a 2.7V--3.6V supply voltage */
+#if STM32_MCU_SERIES == STM32_SERIES_F4
+#define FLASH_SAFE_WAIT_STATES FLASH_WAIT_STATE_2
+#else
+#define FLASH_SAFE_WAIT_STATES FLASH_WAIT_STATE_3
+#endif
+
+/* Flash memory features available via ACR. */
+enum {
+ FLASH_PREFETCH = 0x100,
+ FLASH_ICACHE = 0x200,
+ FLASH_DCACHE = 0x400,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmaple/stm32f2-f4/include/series/gpio.h b/libmaple/stm32f2-f4/include/series/gpio.h
new file mode 100644
index 0000000..4d0d98c
--- /dev/null
+++ b/libmaple/stm32f2-f4/include/series/gpio.h
@@ -0,0 +1,264 @@
+/******************************************************************************
+ * 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 libmaple/stm32f2/include/series/gpio.h
+ * @brief STM32F2 GPIO support.
+ */
+
+#ifndef _LIBMAPLE_STM32F2_GPIO_H_
+#define _LIBMAPLE_STM32F2_GPIO_H_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include <libmaple/libmaple_types.h>
+
+/*
+ * GPIO register maps and devices
+ */
+
+/** GPIO register map type */
+typedef struct gpio_reg_map {
+ __io uint32 MODER; /**< Mode register */
+ __io uint32 OTYPER; /**< Output type register */
+ __io uint32 OSPEEDR; /**< Output speed register */
+ __io uint32 PUPDR; /**< Pull-up/pull-down register */
+ __io uint32 IDR; /**< Input data register */
+ __io uint32 ODR; /**< Output data register */
+ __io uint32 BSRR; /**< Bit set/reset register */
+ __io uint32 LCKR; /**< Configuration lock register */
+ __io uint32 AFRL; /**< Alternate function low register */
+ __io uint32 AFRH; /**< Alternate function high register */
+} gpio_reg_map;
+
+/** GPIO port A register map base pointer */
+#define GPIOA_BASE ((struct gpio_reg_map*)0x40020000)
+/** GPIO port B register map base pointer */
+#define GPIOB_BASE ((struct gpio_reg_map*)0x40020400)
+/** GPIO port C register map base pointer */
+#define GPIOC_BASE ((struct gpio_reg_map*)0x40020800)
+/** GPIO port D register map base pointer */
+#define GPIOD_BASE ((struct gpio_reg_map*)0x40020C00)
+/** GPIO port E register map base pointer */
+#define GPIOE_BASE ((struct gpio_reg_map*)0x40021000)
+/** GPIO port F register map base pointer */
+#define GPIOF_BASE ((struct gpio_reg_map*)0x40021400)
+/** GPIO port G register map base pointer */
+#define GPIOG_BASE ((struct gpio_reg_map*)0x40021800)
+/** GPIO port H register map base pointer */
+#define GPIOH_BASE ((struct gpio_reg_map*)0x40021C00)
+/** GPIO port I register map base pointer */
+#define GPIOI_BASE ((struct gpio_reg_map*)0x40022000)
+
+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
+ *
+ * Currently, we only provide masks to be used for shifting for some
+ * registers, rather than repeating the same values 16 times.
+ */
+
+/* Mode register */
+
+#define GPIO_MODER_INPUT 0x0
+#define GPIO_MODER_OUTPUT 0x1
+#define GPIO_MODER_AF 0x2
+#define GPIO_MODER_ANALOG 0x3
+
+/* Output type register */
+
+#define GPIO_OTYPER_PP 0x0
+#define GPIO_OTYPER_OD 0x1
+
+/* Output speed register */
+
+#define GPIO_OSPEEDR_LOW 0x0
+#define GPIO_OSPEEDR_MED 0x1
+#define GPIO_OSPEEDR_FAST 0x2
+#define GPIO_OSPEEDR_HIGH 0x3
+
+/* Pull-up/pull-down register */
+
+#define GPIO_PUPDR_NOPUPD 0x0
+#define GPIO_PUPDR_PU 0x1
+#define GPIO_PUPDR_PD 0x2
+
+/* Alternate function register low */
+
+#define GPIO_AFRL_AF0 (0xFU << 0)
+#define GPIO_AFRL_AF1 (0xFU << 4)
+#define GPIO_AFRL_AF2 (0xFU << 8)
+#define GPIO_AFRL_AF3 (0xFU << 12)
+#define GPIO_AFRL_AF4 (0xFU << 16)
+#define GPIO_AFRL_AF5 (0xFU << 20)
+#define GPIO_AFRL_AF6 (0xFU << 24)
+#define GPIO_AFRL_AF7 (0xFU << 28)
+
+/* Alternate function register high */
+
+#define GPIO_AFRH_AF8 (0xFU << 0)
+#define GPIO_AFRH_AF9 (0xFU << 4)
+#define GPIO_AFRH_AF10 (0xFU << 8)
+#define GPIO_AFRH_AF11 (0xFU << 12)
+#define GPIO_AFRH_AF12 (0xFU << 16)
+#define GPIO_AFRH_AF13 (0xFU << 20)
+#define GPIO_AFRH_AF14 (0xFU << 24)
+#define GPIO_AFRH_AF15 (0xFU << 28)
+
+/*
+ * GPIO routines
+ */
+
+/**
+ * @brief GPIO pin modes
+ */
+typedef enum gpio_pin_mode {
+ GPIO_MODE_INPUT = GPIO_MODER_INPUT, /**< Input mode */
+ GPIO_MODE_OUTPUT = GPIO_MODER_OUTPUT, /**< Output mode */
+ GPIO_MODE_AF = GPIO_MODER_AF, /**< Alternate function mode */
+ GPIO_MODE_ANALOG = GPIO_MODER_ANALOG, /**< Analog mode */
+} gpio_pin_mode;
+
+/**
+ * @brief Additional flags to be used when setting a pin's mode.
+ *
+ * Beyond the basic modes (input, general purpose output, alternate
+ * function, and analog), there are three parameters that can affect a
+ * pin's mode:
+ *
+ * 1. Output type: push/pull or open-drain. This only has an effect
+ * for output modes. Choices are: GPIO_MODEF_TYPE_PP (the default)
+ * and GPIO_MODEF_TYPE_OD.
+ *
+ * 2. Output speed: specifies the frequency at which a pin changes
+ * state. This only has an effect for output modes. Choices are:
+ * GPIO_MODEF_SPEED_LOW (default), GPIO_MODEF_SPEED_MED,
+ * GPIO_MODEF_SPEED_FAST, and GPIO_MODEF_SPEED_HIGH.
+ *
+ * 3. Push/pull setting: All GPIO pins have weak pull-up and pull-down
+ * resistors that can be enabled when the pin's mode is
+ * set. Choices are: GPIO_MODEF_PUPD_NONE (default),
+ * GPIO_MODEF_PUPD_PU, and GPIO_MODEF_PUPD_PD.
+ */
+typedef enum gpio_mode_flags {
+ /* Output type in bit 0 */
+ GPIO_MODEF_TYPE_PP = GPIO_OTYPER_PP, /**< Output push/pull (default).
+ Applies only when the mode
+ specifies output. */
+ GPIO_MODEF_TYPE_OD = GPIO_OTYPER_OD, /**< Output open drain.
+ Applies only when the mode
+ specifies output. */
+
+ /* Speed in bits 2:1 */
+ GPIO_MODEF_SPEED_LOW = GPIO_OSPEEDR_LOW << 1, /**< Low speed (default):
+ 2 MHz. */
+ GPIO_MODEF_SPEED_MED = GPIO_OSPEEDR_MED << 1, /**< Medium speed: 25 MHz. */
+ GPIO_MODEF_SPEED_FAST = GPIO_OSPEEDR_FAST << 1, /**< Fast speed: 50 MHz. */
+ GPIO_MODEF_SPEED_HIGH = GPIO_OSPEEDR_HIGH << 1, /**< High speed:
+ 100 MHz on 30 pF,
+ 80 MHz on 15 pF. */
+
+ /* Pull-up/pull-down in bits 4:3 */
+ GPIO_MODEF_PUPD_NONE = GPIO_PUPDR_NOPUPD << 3, /**< No pull-up/pull-down
+ (default). */
+ GPIO_MODEF_PUPD_PU = GPIO_PUPDR_PU << 3, /**< Pull-up */
+ GPIO_MODEF_PUPD_PD = GPIO_PUPDR_PD << 3, /**< Pull-down */
+} gpio_mode_flags;
+
+void gpio_set_modef(struct gpio_dev *dev,
+ uint8 bit,
+ gpio_pin_mode mode,
+ unsigned flags);
+
+/**
+ * @brief Set the mode of a GPIO pin.
+ *
+ * Calling this function is equivalent to calling gpio_set_modef(dev,
+ * pin, mode, GPIO_MODE_SPEED_HIGH). Note that this overrides the
+ * default speed.
+ *
+ * @param dev GPIO device.
+ * @param bit Bit on the device whose mode to set, 0--15.
+ * @param mode Mode to set the pin to.
+ */
+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);
+}
+
+/**
+ * @brief GPIO alternate functions.
+ * Use these to select an alternate function for a pin.
+ * @see gpio_set_af()
+ */
+typedef enum gpio_af {
+ GPIO_AF_SYS = 0, /**< System. */
+ GPIO_AF_TIM_1_2 = 1, /**< Timers 1 and 2. */
+ GPIO_AF_TIM_3_4_5 = 2, /**< Timers 3, 4, and 5. */
+ GPIO_AF_TIM_8_9_10_11 = 3, /**< Timers 8 through 11. */
+ GPIO_AF_I2C = 4, /**< I2C 1, 2, and 3. */
+ GPIO_AF_SPI_1_2 = 5, /**< SPI1, SPI2/I2S2. */
+ GPIO_AF_SPI3 = 6, /**< SPI3/I2S3. */
+ GPIO_AF_USART_1_2_3 = 7, /**< USART 1, 2, and 3. */
+ GPIO_AF_USART_4_5_6 = 8, /**< UART 4 and 5, USART 6. */
+ GPIO_AF_CAN_1_2_TIM_12_13_14 = 9, /**<
+ * CAN 1 and 2, timers 12, 13, and 14. */
+ GPIO_AF_USB_OTG_FS_HS = 10, /**< USB OTG HS and FS. */
+ GPIO_AF_ETH = 11, /**< Ethernet MII and RMII. */
+ GPIO_AF_FSMC_SDIO_OTG_FS = 12, /**< FSMC, SDIO, and USB OTG FS. */
+ GPIO_AF_DCMI = 13, /**< DCMI. */
+ GPIO_AF_EVENTOUT = 15, /**< EVENTOUT. */
+} gpio_af;
+
+void gpio_set_af(struct gpio_dev *dev, uint8 bit, gpio_af af);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmaple/stm32f2-f4/include/series/i2c.h b/libmaple/stm32f2-f4/include/series/i2c.h
new file mode 100644
index 0000000..b231256
--- /dev/null
+++ b/libmaple/stm32f2-f4/include/series/i2c.h
@@ -0,0 +1,80 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2010 Perry Hung (from <libmaple/i2c.h>).
+ * Copyright (c) 2012 LeafLabs, LLC.
+ * Copyright (c) 2014 Google, Inc.
+ *
+ * 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_STM32F2_I2C_H_
+#define _LIBMAPLE_STM32F2_I2C_H_
+
+#include <libmaple/i2c_common.h>
+#include <libmaple/stm32.h>
+
+/*
+ * Register maps
+ */
+
+/** I2C register map type */
+typedef struct i2c_reg_map {
+ __io uint32 CR1; /**< Control register 1 */
+ __io uint32 CR2; /**< Control register 2 */
+ __io uint32 OAR1; /**< Own address register 1 */
+ __io uint32 OAR2; /**< Own address register 2 */
+ __io uint32 DR; /**< Data register */
+ __io uint32 SR1; /**< Status register 1 */
+ __io uint32 SR2; /**< Status register 2 */
+ __io uint32 CCR; /**< Clock control register */
+ __io uint32 TRISE; /**< TRISE (rise time) register */
+ __io uint32 FLTR; /**< Noise filter register */
+} i2c_reg_map;
+
+/** I2C1 register map base pointer */
+#define I2C1_BASE ((struct i2c_reg_map*)0x40005400)
+/** I2C2 register map base pointer */
+#define I2C2_BASE ((struct i2c_reg_map*)0x40005800)
+/** I2C3 register map base pointer */
+#define I2C3_BASE ((struct i2c_reg_map*)0x40005C00)
+
+/*
+ * Devices
+ */
+
+extern i2c_dev* const I2C1;
+extern i2c_dev* const I2C2;
+extern i2c_dev* const I2C3;
+
+/*
+ * For internal use
+ */
+
+static inline uint32 _i2c_bus_clk(i2c_dev *dev) {
+ /* All the I2C peripherals are on APB1 */
+ return STM32_PCLK1 / (1000 * 1000);
+}
+
+#undef _I2C_HAVE_IRQ_FIXUP
+#undef _I2C_HAVE_DEPRECATED_I2C_REMAP
+
+#endif /* _LIBMAPLE_STM32F1_I2C_H_ */
diff --git a/libmaple/stm32f2-f4/include/series/nvic.h b/libmaple/stm32f2-f4/include/series/nvic.h
new file mode 100644
index 0000000..dc03806
--- /dev/null
+++ b/libmaple/stm32f2-f4/include/series/nvic.h
@@ -0,0 +1,160 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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/nvic.h
+ * @brief STM32F2 nested vectored interrupt controller (NVIC) header.
+ */
+
+#ifndef _LIBMAPLE_STM32F2_NVIC_H_
+#define _LIBMAPLE_STM32F2_NVIC_H_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/**
+ * @brief STM32F2 interrupt vector table interrupt numbers.
+ */
+typedef enum nvic_irq_num {
+ NVIC_NMI = -14, /**< Non-maskable interrupt */
+ NVIC_HARDFAULT = -13, /**< Hard fault (all class of fault) */
+ NVIC_MEM_MANAGE = -12, /**< Memory management */
+ NVIC_BUS_FAULT = -11, /**< Bus fault: prefetch fault, memory
+ access fault. */
+ NVIC_USAGE_FAULT = -10, /**< Usage fault: Undefined instruction
+ or illegal state. */
+ NVIC_SVC = -5, /**< System service call via SWI
+ instruction */
+ NVIC_DEBUG_MON = -4, /**< Debug monitor */
+ NVIC_PEND_SVC = -2, /**< Pendable request for system
+ service */
+ NVIC_SYSTICK = -1, /**< System tick timer */
+ NVIC_WWDG = 0, /**< Window watchdog interrupt */
+ NVIC_PVD = 1, /**< PVD through EXTI line detection */
+ NVIC_TAMP_STAMP = 2, /**< Tamper and TimeStamp */
+ NVIC_RTC_WKUP = 3, /**< Real-time clock wakeup */
+ NVIC_FLASH = 4, /**< Flash */
+ NVIC_RCC = 5, /**< Reset and clock control */
+ NVIC_EXTI0 = 6, /**< EXTI line 0 */
+ NVIC_EXTI1 = 7, /**< EXTI line 1 */
+ NVIC_EXTI2 = 8, /**< EXTI line 2 */
+ NVIC_EXTI3 = 9, /**< EXTI line 3 */
+ NVIC_EXTI4 = 10, /**< EXTI line 4 */
+ NVIC_DMA1_STREAM0 = 11, /**< DMA1 stream 0 */
+ NVIC_DMA1_STREAM1 = 12, /**< DMA1 stream 1 */
+ NVIC_DMA1_STREAM2 = 13, /**< DMA1 stream 2 */
+ NVIC_DMA1_STREAM3 = 14, /**< DMA1 stream 3 */
+ NVIC_DMA1_STREAM4 = 15, /**< DMA1 stream 4 */
+ NVIC_DMA1_STREAM5 = 16, /**< DMA1 stream 5 */
+ NVIC_DMA1_STREAM6 = 17, /**< DMA1 stream 6 */
+ NVIC_ADC = 18, /**< ADC */
+ NVIC_CAN1_TX = 19, /**< CAN1 TX */
+ NVIC_CAN1_RX0 = 20, /**< CAN1 RX0 */
+ NVIC_CAN1_RX1 = 21, /**< CAN1 RX1 */
+ NVIC_CAN1_SCE = 22, /**< CAN1 SCE */
+ NVIC_EXTI_9_5 = 23, /**< EXTI lines [9:5] */
+ NVIC_TIMER1_BRK_TIMER9 = 24, /**< Timer 1 break and timer 9 */
+ NVIC_TIMER1_UP_TIMER10 = 25, /**< Timer 1 update and timer 10 */
+ NVIC_TIMER1_TRG_COM_TIMER11 = 26, /**< Timer 1 trigger and commutation and
+ timer 11.*/
+ NVIC_TIMER1_CC = 27, /**< Timer 1 capture and compare */
+ NVIC_TIMER2 = 28, /**< Timer 2 */
+ NVIC_TIMER3 = 29, /**< Timer 3 */
+ NVIC_TIMER4 = 30, /**< Timer 4 */
+ NVIC_I2C1_EV = 31, /**< I2C1 event */
+ NVIC_I2C1_ER = 32, /**< I2C2 error */
+ NVIC_I2C2_EV = 33, /**< I2C2 event */
+ NVIC_I2C2_ER = 34, /**< I2C2 error */
+ NVIC_SPI1 = 35, /**< SPI1 */
+ NVIC_SPI2 = 36, /**< SPI2 */
+ NVIC_USART1 = 37, /**< USART1 */
+ NVIC_USART2 = 38, /**< USART2 */
+ NVIC_USART3 = 39, /**< USART3 */
+ NVIC_EXTI_15_10 = 40, /**< EXTI lines [15:10] */
+ NVIC_RTCALARM = 41, /**< RTC alarms A and B through EXTI */
+ NVIC_OTG_FS_WKUP = 42, /**< USB on-the-go full-speed wakeup
+ through EXTI*/
+ NVIC_TIMER8_BRK_TIMER12 = 43, /**< Timer 8 break and timer 12 */
+ NVIC_TIMER8_UP_TIMER13 = 44, /**< Timer 8 update and timer 13 */
+ NVIC_TIMER8_TRG_COM_TIMER14 = 45, /**< Timer 8 trigger and commutation and
+ timer 14 */
+ NVIC_TIMER8_CC = 46, /**< Timer 8 capture and compare */
+ NVIC_DMA1_STREAM7 = 47, /**< DMA1 stream 7 */
+ NVIC_FSMC = 48, /**< FSMC */
+ NVIC_SDIO = 49, /**< SDIO */
+ NVIC_TIMER5 = 50, /**< Timer 5 */
+ NVIC_SPI3 = 51, /**< SPI3 */
+ NVIC_UART4 = 52, /**< UART4 */
+ NVIC_UART5 = 53, /**< UART5 */
+ NVIC_TIMER6_DAC = 54, /**< Timer 6 and DAC underrun */
+ NVIC_TIMER7 = 55, /**< Timer 7 */
+ NVIC_DMA2_STREAM0 = 56, /**< DMA2 stream 0 */
+ NVIC_DMA2_STREAM1 = 57, /**< DMA2 stream 1 */
+ NVIC_DMA2_STREAM2 = 58, /**< DMA2 stream 2 */
+ NVIC_DMA2_STREAM3 = 59, /**< DMA2 stream 3 */
+ NVIC_DMA2_STREAM4 = 60, /**< DMA2 stream 4 */
+ NVIC_ETH = 61, /**< Ethernet */
+ NVIC_ETH_WKUP = 62, /**< Ethernet wakeup through EXTI */
+ NVIC_CAN2_TX = 63, /**< CAN2 TX */
+ NVIC_CAN2_RX0 = 64, /**< CAN2 RX0 */
+ NVIC_CAN2_RX1 = 65, /**< CAN2 RX1 */
+ NVIC_CAN2_SCE = 66, /**< CAN2 SCE */
+ NVIC_OTG_FS = 67, /**< USB on-the-go full-speed */
+ NVIC_DMA2_STREAM5 = 68, /**< DMA2 stream 5 */
+ NVIC_DMA2_STREAM6 = 69, /**< DMA2 stream 6 */
+ NVIC_DMA2_STREAM7 = 70, /**< DMA2 stream 7 */
+ NVIC_USART6 = 71, /**< USART6 */
+ NVIC_I2C3_EV = 72, /**< I2C3 event */
+ NVIC_I2C3_ER = 73, /**< I2C3 error */
+ NVIC_OTG_HS_EP1_OUT = 74, /**< USB on-the-go high-speed
+ endpoint 1 OUT */
+ NVIC_OTG_HS_EP1_IN = 75, /**< USB on-the-go high-speed
+ endpoint 1 IN */
+ NVIC_OTG_HS_WKUP = 76, /**< USB on-the-go high-speed wakeup
+ through EXTI*/
+ NVIC_OTG_HS = 77, /**< USB on-the-go high-speed */
+ NVIC_DCMI = 78, /**< DCMI */
+ NVIC_CRYP = 79, /**< Cryptographic processor */
+ NVIC_HASH_RNG = 80, /**< Hash and random number
+ generation */
+
+ /* Fake enumerator values, for compatiblity with F1.
+ * TODO decide if this is actually a good idea. */
+ NVIC_TIMER6 = NVIC_TIMER6_DAC, /**< For compatibility with STM32F1. */
+} nvic_irq_num;
+
+static inline void nvic_irq_disable_all(void) {
+ NVIC_BASE->ICER[0] = 0xFFFFFFFF;
+ NVIC_BASE->ICER[1] = 0xFFFFFFFF;
+ NVIC_BASE->ICER[2] = 0xFFFFFFFF;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmaple/stm32f2-f4/include/series/pwr.h b/libmaple/stm32f2-f4/include/series/pwr.h
new file mode 100644
index 0000000..96353a4
--- /dev/null
+++ b/libmaple/stm32f2-f4/include/series/pwr.h
@@ -0,0 +1,73 @@
+/******************************************************************************
+ * 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/pwr.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F2 Power control (PWR) support.
+ */
+
+#ifndef _LIBMAPLE_STM32F2_PWR_H_
+#define _LIBMAPLE_STM32F2_PWR_H_
+
+/*
+ * Additional register bits
+ */
+
+/* Control register */
+
+/**
+ * @brief Flash power down in stop mode bit.
+ * Availability: STM32F2 */
+#define PWR_CR_FPDS_BIT 9
+/**
+ * @brief Flash power down in stop mode.
+ * Availability: STM32F2 */
+#define PWR_CR_FPDS (1U << PWR_CR_FPDS_BIT)
+
+/* PVD level selection */
+#define PWR_CR_PLS_2_0V (0x0 << 5)
+#define PWR_CR_PLS_2_1V (0x1 << 5)
+#define PWR_CR_PLS_2_3V (0x2 << 5)
+#define PWR_CR_PLS_2_5V (0x3 << 5)
+#define PWR_CR_PLS_2_6V (0x4 << 5)
+#define PWR_CR_PLS_2_7V (0x5 << 5)
+#define PWR_CR_PLS_2_8V (0x6 << 5)
+#define PWR_CR_PLS_2_9V (0x7 << 5)
+
+/* Control/Status register */
+
+/** Backup regulator enable bit. */
+#define PWR_CSR_BRE_BIT 9
+/** Backup regulator ready bit. */
+#define PWR_CSR_BRR_BIT 3
+
+/** Backup regulator enable. */
+#define PWR_CSR_BRE (1U << PWR_CSR_BRE_BIT)
+/** Backup regulator ready. */
+#define PWR_CSR_BRR (1U << PWR_CSR_BRR_BIT)
+
+#endif
diff --git a/libmaple/stm32f2-f4/include/series/rcc.h b/libmaple/stm32f2-f4/include/series/rcc.h
new file mode 100644
index 0000000..7cb7df1
--- /dev/null
+++ b/libmaple/stm32f2-f4/include/series/rcc.h
@@ -0,0 +1,955 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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/rcc.h
+ * @brief STM32F2 reset and clock control (RCC) support.
+ */
+
+#ifndef _LIBMAPLE_STM32F2_RCC_H_
+#define _LIBMAPLE_STM32F2_RCC_H_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include <libmaple/libmaple_types.h>
+
+/*
+ * Register map
+ */
+
+/** STM32F2 RCC register map type */
+typedef struct rcc_reg_map {
+ __io uint32 CR; /**< Clock control register */
+ __io uint32 PLLCFGR; /**< PLL configuration register */
+ __io uint32 CFGR; /**< Clock configuration register */
+ __io uint32 CIR; /**< Clock interrupt register */
+ __io uint32 AHB1RSTR; /**< AHB1 peripheral reset register */
+ __io uint32 AHB2RSTR; /**< AHB2 peripheral reset register */
+ __io uint32 AHB3RSTR; /**< AHB3 peripheral reset register */
+ const uint32 RESERVED1; /**< Reserved */
+ __io uint32 APB1RSTR; /**< APB1 peripheral reset register */
+ __io uint32 APB2RSTR; /**< APB2 peripheral reset register */
+ const uint32 RESERVED2; /**< Reserved */
+ const uint32 RESERVED3; /**< Reserved */
+ __io uint32 AHB1ENR; /**< AHB1 peripheral clock enable register */
+ __io uint32 AHB2ENR; /**< AHB2 peripheral clock enable register */
+ __io uint32 AHB3ENR; /**< AHB3 peripheral clock enable register */
+ const uint32 RESERVED4; /**< Reserved */
+ __io uint32 APB1ENR; /**< APB1 peripheral clock enable register */
+ __io uint32 APB2ENR; /**< APB2 peripheral clock enable register */
+ const uint32 RESERVED5; /**< Reserved */
+ const uint32 RESERVED6; /**< Reserved */
+ __io uint32 AHB1LPENR; /**< AHB1 peripheral clock enable in
+ low power mode register */
+ __io uint32 AHB2LPENR; /**< AHB2 peripheral clock enable in
+ low power mode register */
+ __io uint32 AHB3LPENR; /**< AHB3 peripheral clock enable in
+ low power mode register */
+ const uint32 RESERVED7; /**< Reserved */
+ __io uint32 APB1LPENR; /**< APB1 peripheral clock enable in
+ low power mode register */
+ __io uint32 APB2LPENR; /**< APB2 peripheral clock enable in
+ low power mode register */
+ const uint32 RESERVED8; /**< Reserved */
+ const uint32 RESERVED9; /**< Reserved */
+ __io uint32 BDCR; /**< Backup domain control register */
+ __io uint32 CSR; /**< Clock control and status register */
+ const uint32 RESERVED10; /**< Reserved */
+ const uint32 RESERVED11; /**< Reserved */
+ __io uint32 SSCGR; /**< Spread spectrum clock generation
+ register */
+ __io uint32 PLLI2SCFGR; /**< PLLI2S configuration register */
+} rcc_reg_map;
+
+#define RCC_BASE ((struct rcc_reg_map*)0x40023800)
+
+/*
+ * Register bit definitions
+ */
+
+/* Clock control register */
+
+#define RCC_CR_PLLI2SRDY_BIT 27
+#define RCC_CR_PLLI2SON_BIT 26
+#define RCC_CR_PLLRDY_BIT 25
+#define RCC_CR_PLLON_BIT 24
+#define RCC_CR_CSSON_BIT 19
+#define RCC_CR_HSEBYP_BIT 18
+#define RCC_CR_HSERDY_BIT 17
+#define RCC_CR_HSEON_BIT 16
+#define RCC_CR_HSIRDY_BIT 1
+#define RCC_CR_HSION_BIT 0
+
+#define RCC_CR_PLLI2SRDY (1U << RCC_CR_PLLI2SRDY_BIT)
+#define RCC_CR_PLLI2SON (1U << RCC_CR_PLLI2SON_BIT)
+#define RCC_CR_PLLRDY (1U << RCC_CR_PLLRDY_BIT)
+#define RCC_CR_PLLON (1U << RCC_CR_PLLON_BIT)
+#define RCC_CR_CSSON (1U << RCC_CR_CSSON_BIT)
+#define RCC_CR_HSEBYP (1U << RCC_CR_HSEBYP_BIT)
+#define RCC_CR_HSERDY (1U << RCC_CR_HSERDY_BIT)
+#define RCC_CR_HSEON (1U << RCC_CR_HSEON_BIT)
+#define RCC_CR_HSICAL (0xFF << 8)
+#define RCC_CR_HSITRIM (0x1F << 3)
+#define RCC_CR_HSIRDY (1U << RCC_CR_HSIRDY_BIT)
+#define RCC_CR_HSION (1U << RCC_CR_HSION_BIT)
+
+/* PLL configuration register */
+
+#define RCC_PLLCFGR_PLLSRC_BIT 22
+
+#define RCC_PLLCFGR_PLLQ (0xF << 24)
+#define RCC_PLLCFGR_PLLSRC (1U << RCC_PLLCFGR_PLLSRC_BIT)
+#define RCC_PLLCFGR_PLLSRC_HSI (0x0 << RCC_PLLCFGR_PLLSRC_BIT)
+#define RCC_PLLCFGR_PLLSRC_HSE (0x1 << RCC_PLLCFGR_PLLSRC_BIT)
+#define RCC_PLLCFGR_PLLP (0x3 << 16)
+#define RCC_PLLCFGR_PLLN (0x1FF << 6)
+#if STM32_MCU_SERIES == STM32_SERIES_F4
+# define RCC_PLLCFGR_PLLM 0x3F
+#else
+# define RCC_PLLCFGR_PLLM 0x1F
+#endif
+
+/* Clock configuration register */
+
+#define RCC_CFGR_I2SSRC_BIT 23
+
+#define RCC_CFGR_MCO2 (0x3 << 30)
+#define RCC_CFGR_MCO2_SYSCLK (0x0 << 30)
+#define RCC_CFGR_MCO2_PLLI2S (0x1 << 30)
+#define RCC_CFGR_MCO2_HSE (0x2 << 30)
+#define RCC_CFGR_MCO2_PLL (0x3 << 30)
+
+#define RCC_CFGR_MCO2PRE (0x7 << 27)
+#define RCC_CFGR_MCO2PRE_DIV_1 (0x0 << 27)
+#define RCC_CFGR_MCO2PRE_DIV_2 (0x4 << 27)
+#define RCC_CFGR_MCO2PRE_DIV_3 (0x5 << 27)
+#define RCC_CFGR_MCO2PRE_DIV_4 (0x6 << 27)
+#define RCC_CFGR_MCO2PRE_DIV_5 (0x7 << 27)
+
+#define RCC_CFGR_MCO1PRE (0x7 << 24)
+#define RCC_CFGR_MCO1PRE_DIV_1 (0x0 << 24)
+#define RCC_CFGR_MCO1PRE_DIV_2 (0x4 << 24)
+#define RCC_CFGR_MCO1PRE_DIV_3 (0x5 << 24)
+#define RCC_CFGR_MCO1PRE_DIV_4 (0x6 << 24)
+#define RCC_CFGR_MCO1PRE_DIV_5 (0x7 << 24)
+
+#define RCC_CFGR_I2SSRC (1U << RCC_CFGR_I2SSRC_BIT)
+#define RCC_CFGR_I2SSRC_PLLI2S (0 << RCC_CFGR_I2SSRC_BIT)
+#define RCC_CFGR_I2SSRC_I2S_CKIN (1 << RCC_CFGR_I2SSRC_BIT)
+
+#define RCC_CFGR_MCO1 (0x3 << 21)
+#define RCC_CFGR_MCO1_HSI (0x0 << 21)
+#define RCC_CFGR_MCO1_LSE (0x1 << 21)
+#define RCC_CFGR_MCO1_HSE (0x2 << 21)
+#define RCC_CFGR_MCO1_PLL (0x3 << 21)
+
+#define RCC_CFGR_RTCPRE (0x1F << 16)
+
+/* Skipped: all the 0b0xx values meaning "not divided" */
+#define RCC_CFGR_PPRE2 (0x7 << 13)
+#define RCC_CFGR_PPRE2_AHB_DIV_2 (0x4 << 13)
+#define RCC_CFGR_PPRE2_AHB_DIV_4 (0x5 << 13)
+#define RCC_CFGR_PPRE2_AHB_DIV_8 (0x6 << 13)
+#define RCC_CFGR_PPRE2_AHB_DIV_16 (0x7 << 13)
+
+/* Skipped: all the 0b0xx values meaning "not divided" */
+#define RCC_CFGR_PPRE1 (0x7 << 10)
+#define RCC_CFGR_PPRE1_AHB_DIV_2 (0x4 << 10)
+#define RCC_CFGR_PPRE1_AHB_DIV_4 (0x5 << 10)
+#define RCC_CFGR_PPRE1_AHB_DIV_8 (0x6 << 10)
+#define RCC_CFGR_PPRE1_AHB_DIV_16 (0x7 << 10)
+
+/* Skipped: all the 0b0xxx values meaning "not divided" */
+#define RCC_CFGR_HPRE (0xF << 4)
+#define RCC_CFGR_HPRE_SYSCLK_DIV_2 (0x8 << 4)
+#define RCC_CFGR_HPRE_SYSCLK_DIV_4 (0x9 << 4)
+#define RCC_CFGR_HPRE_SYSCLK_DIV_8 (0xA << 4)
+#define RCC_CFGR_HPRE_SYSCLK_DIV_16 (0xB << 4)
+#define RCC_CFGR_HPRE_SYSCLK_DIV_64 (0xC << 4)
+#define RCC_CFGR_HPRE_SYSCLK_DIV_128 (0xD << 4)
+#define RCC_CFGR_HPRE_SYSCLK_DIV_256 (0xE << 4)
+#define RCC_CFGR_HPRE_SYSCLK_DIV_512 (0xF << 4)
+
+#define RCC_CFGR_SWS (0x3 << 2)
+#define RCC_CFGR_SWS_HSI (0x0 << 2)
+#define RCC_CFGR_SWS_HSE (0x1 << 2)
+#define RCC_CFGR_SWS_PLL (0x2 << 2)
+
+#define RCC_CFGR_SW 0x3
+#define RCC_CFGR_SW_HSI 0x0
+#define RCC_CFGR_SW_HSE 0x1
+#define RCC_CFGR_SW_PLL 0x2
+
+/* Clock interrupt register */
+
+#define RCC_CIR_CSSC_BIT 23
+
+#define RCC_CIR_PLLI2SRDYC_BIT 21
+#define RCC_CIR_PLLRDYC_BIT 20
+#define RCC_CIR_HSERDYC_BIT 19
+#define RCC_CIR_HSIRDYC_BIT 18
+#define RCC_CIR_LSERDYC_BIT 17
+#define RCC_CIR_LSIRDYC_BIT 16
+
+#define RCC_CIR_PLLI2SRDYIE_BIT 13
+#define RCC_CIR_PLLRDYIE_BIT 12
+#define RCC_CIR_HSERDYIE_BIT 11
+#define RCC_CIR_HSIRDYIE_BIT 10
+#define RCC_CIR_LSERDYIE_BIT 9
+#define RCC_CIR_LSIRDYIE_BIT 8
+
+#define RCC_CIR_CSSF_BIT 7
+
+#define RCC_CIR_PLLI2SRDYF_BIT 5
+#define RCC_CIR_PLLRDYF_BIT 4
+#define RCC_CIR_HSERDYF_BIT 3
+#define RCC_CIR_HSIRDYF_BIT 2
+#define RCC_CIR_LSERDYF_BIT 1
+#define RCC_CIR_LSIRDYF_BIT 0
+
+#define RCC_CIR_CSSC (1U << RCC_CIR_CSSC_BIT)
+
+#define RCC_CIR_PLLI2SRDYC (1U << RCC_CIR_PLLI2SRDYC_BIT)
+#define RCC_CIR_PLLRDYC (1U << RCC_CIR_PLLRDYC_BIT)
+#define RCC_CIR_HSERDYC (1U << RCC_CIR_HSERDYC_BIT)
+#define RCC_CIR_HSIRDYC (1U << RCC_CIR_HSIRDYC_BIT)
+#define RCC_CIR_LSERDYC (1U << RCC_CIR_LSERDYC_BIT)
+#define RCC_CIR_LSIRDYC (1U << RCC_CIR_LSIRDYC_BIT)
+
+#define RCC_CIR_PLLI2SRDYIE (1U << RCC_CIR_PLLI2SRDYIE_BIT)
+#define RCC_CIR_PLLRDYIE (1U << RCC_CIR_PLLRDYIE_BIT)
+#define RCC_CIR_HSERDYIE (1U << RCC_CIR_HSERDYIE_BIT)
+#define RCC_CIR_HSIRDYIE (1U << RCC_CIR_HSIRDYIE_BIT)
+#define RCC_CIR_LSERDYIE (1U << RCC_CIR_LSERDYIE_BIT)
+#define RCC_CIR_LSIRDYIE (1U << RCC_CIR_LSIRDYIE_BIT)
+
+#define RCC_CIR_CSSF (1U << RCC_CIR_CSSF_BIT)
+
+#define RCC_CIR_PLLI2SRDYF (1U << RCC_CIR_PLLI2SRDYF_BIT)
+#define RCC_CIR_PLLRDYF (1U << RCC_CIR_PLLRDYF_BIT)
+#define RCC_CIR_HSERDYF (1U << RCC_CIR_HSERDYF_BIT)
+#define RCC_CIR_HSIRDYF (1U << RCC_CIR_HSIRDYF_BIT)
+#define RCC_CIR_LSERDYF (1U << RCC_CIR_LSERDYF_BIT)
+#define RCC_CIR_LSIRDYF (1U << RCC_CIR_LSIRDYF_BIT)
+
+/* AHB1 peripheral reset register */
+
+#define RCC_AHB1RSTR_OTGHSRST_BIT 29
+#define RCC_AHB1RSTR_ETHMACRST_BIT 25
+#define RCC_AHB1RSTR_DMA2RST_BIT 22
+#define RCC_AHB1RSTR_DMA1RST_BIT 21
+#define RCC_AHB1RSTR_CRCRST_BIT 12
+#define RCC_AHB1RSTR_GPIOIRST_BIT 8
+#define RCC_AHB1RSTR_GPIOHRST_BIT 7
+#define RCC_AHB1RSTR_GPIOGRST_BIT 6
+#define RCC_AHB1RSTR_GPIOFRST_BIT 5
+#define RCC_AHB1RSTR_GPIOERST_BIT 4
+#define RCC_AHB1RSTR_GPIODRST_BIT 3
+#define RCC_AHB1RSTR_GPIOCRST_BIT 2
+#define RCC_AHB1RSTR_GPIOBRST_BIT 1
+#define RCC_AHB1RSTR_GPIOARST_BIT 0
+
+#define RCC_AHB1RSTR_OTGHSRST (1U << RCC_AHB1RSTR_OTGHSRST_BIT)
+#define RCC_AHB1RSTR_ETHMACRST (1U << RCC_AHB1RSTR_ETHMACRST_BIT)
+#define RCC_AHB1RSTR_DMA2RST (1U << RCC_AHB1RSTR_DMA2RST_BIT)
+#define RCC_AHB1RSTR_DMA1RST (1U << RCC_AHB1RSTR_DMA1RST_BIT)
+#define RCC_AHB1RSTR_CRCRST (1U << RCC_AHB1RSTR_CRCRST_BIT)
+#define RCC_AHB1RSTR_GPIOIRST (1U << RCC_AHB1RSTR_GPIOIRST_BIT)
+#define RCC_AHB1RSTR_GPIOHRST (1U << RCC_AHB1RSTR_GPIOHRST_BIT)
+#define RCC_AHB1RSTR_GPIOGRST (1U << RCC_AHB1RSTR_GPIOGRST_BIT)
+#define RCC_AHB1RSTR_GPIOFRST (1U << RCC_AHB1RSTR_GPIOFRST_BIT)
+#define RCC_AHB1RSTR_GPIOERST (1U << RCC_AHB1RSTR_GPIOERST_BIT)
+#define RCC_AHB1RSTR_GPIODRST (1U << RCC_AHB1RSTR_GPIODRST_BIT)
+#define RCC_AHB1RSTR_GPIOCRST (1U << RCC_AHB1RSTR_GPIOCRST_BIT)
+#define RCC_AHB1RSTR_GPIOBRST (1U << RCC_AHB1RSTR_GPIOBRST_BIT)
+#define RCC_AHB1RSTR_GPIOARST (1U << RCC_AHB1RSTR_GPIOARST_BIT)
+
+/* AHB2 peripheral reset register */
+
+#define RCC_AHB2RSTR_OTGFSRST_BIT 7
+#define RCC_AHB2RSTR_RNGRST_BIT 6
+#define RCC_AHB2RSTR_HASHRST_BIT 5
+#define RCC_AHB2RSTR_CRYPRST_BIT 4
+#define RCC_AHB2RSTR_DCMIRST_BIT 0
+
+#define RCC_AHB2RSTR_OTGFSRST (1U << RCC_AHB2RSTR_OTGFSRST_BIT)
+#define RCC_AHB2RSTR_RNGRST (1U << RCC_AHB2RSTR_RNGRST_BIT)
+#define RCC_AHB2RSTR_HASHRST (1U << RCC_AHB2RSTR_HASHRST_BIT)
+#define RCC_AHB2RSTR_CRYPRST (1U << RCC_AHB2RSTR_CRYPRST_BIT)
+#define RCC_AHB2RSTR_DCMIRST (1U << RCC_AHB2RSTR_DCMIRST_BIT)
+
+/* AHB3 peripheral reset register */
+
+#define RCC_AHB3RSTR_FSMCRST_BIT 0
+
+#define RCC_AHB3RSTR_FSMCRST (1U << RCC_AHB3RSTR_FSMCRST_BIT)
+
+/* APB1 peripheral reset register */
+
+#define RCC_APB1RSTR_DACRST_BIT 29
+#define RCC_APB1RSTR_PWRRST_BIT 28
+#define RCC_APB1RSTR_CAN2RST_BIT 26
+#define RCC_APB1RSTR_CAN1RST_BIT 25
+#define RCC_APB1RSTR_I2C3RST_BIT 23
+#define RCC_APB1RSTR_I2C2RST_BIT 22
+#define RCC_APB1RSTR_I2C1RST_BIT 21
+#define RCC_APB1RSTR_UART5RST_BIT 20
+#define RCC_APB1RSTR_UART4RST_BIT 19
+#define RCC_APB1RSTR_UART3RST_BIT 18
+#define RCC_APB1RSTR_UART2RST_BIT 17
+#define RCC_APB1RSTR_SPI3RST_BIT 15
+#define RCC_APB1RSTR_SPI2RST_BIT 14
+#define RCC_APB1RSTR_WWDGRST_BIT 11
+#define RCC_APB1RSTR_TIM14RST_BIT 8
+#define RCC_APB1RSTR_TIM13RST_BIT 7
+#define RCC_APB1RSTR_TIM12RST_BIT 6
+#define RCC_APB1RSTR_TIM7RST_BIT 5
+#define RCC_APB1RSTR_TIM6RST_BIT 4
+#define RCC_APB1RSTR_TIM5RST_BIT 3
+#define RCC_APB1RSTR_TIM4RST_BIT 2
+#define RCC_APB1RSTR_TIM3RST_BIT 1
+#define RCC_APB1RSTR_TIM2RST_BIT 0
+
+#define RCC_APB1RSTR_DACRST (1U << RCC_APB1RSTR_DACRST_BIT)
+#define RCC_APB1RSTR_PWRRST (1U << RCC_APB1RSTR_PWRRST_BIT)
+#define RCC_APB1RSTR_CAN2RST (1U << RCC_APB1RSTR_CAN2RST_BIT)
+#define RCC_APB1RSTR_CAN1RST (1U << RCC_APB1RSTR_CAN1RST_BIT)
+#define RCC_APB1RSTR_I2C3RST (1U << RCC_APB1RSTR_I2C3RST_BIT)
+#define RCC_APB1RSTR_I2C2RST (1U << RCC_APB1RSTR_I2C2RST_BIT)
+#define RCC_APB1RSTR_I2C1RST (1U << RCC_APB1RSTR_I2C1RST_BIT)
+#define RCC_APB1RSTR_UART5RST (1U << RCC_APB1RSTR_UART5RST_BIT)
+#define RCC_APB1RSTR_UART4RST (1U << RCC_APB1RSTR_UART4RST_BIT)
+#define RCC_APB1RSTR_UART3RST (1U << RCC_APB1RSTR_UART3RST_BIT)
+#define RCC_APB1RSTR_UART2RST (1U << RCC_APB1RSTR_UART2RST_BIT)
+#define RCC_APB1RSTR_SPI3RST (1U << RCC_APB1RSTR_SPI3RST_BIT)
+#define RCC_APB1RSTR_SPI2RST (1U << RCC_APB1RSTR_SPI2RST_BIT)
+#define RCC_APB1RSTR_WWDGRST (1U << RCC_APB1RSTR_WWDGRST_BIT)
+#define RCC_APB1RSTR_TIM14RST (1U << RCC_APB1RSTR_TIM14RST_BIT)
+#define RCC_APB1RSTR_TIM13RST (1U << RCC_APB1RSTR_TIM13RST_BIT)
+#define RCC_APB1RSTR_TIM12RST (1U << RCC_APB1RSTR_TIM12RST_BIT)
+#define RCC_APB1RSTR_TIM7RST (1U << RCC_APB1RSTR_TIM7RST_BIT)
+#define RCC_APB1RSTR_TIM6RST (1U << RCC_APB1RSTR_TIM6RST_BIT)
+#define RCC_APB1RSTR_TIM5RST (1U << RCC_APB1RSTR_TIM5RST_BIT)
+#define RCC_APB1RSTR_TIM4RST (1U << RCC_APB1RSTR_TIM4RST_BIT)
+#define RCC_APB1RSTR_TIM3RST (1U << RCC_APB1RSTR_TIM3RST_BIT)
+#define RCC_APB1RSTR_TIM2RST (1U << RCC_APB1RSTR_TIM2RST_BIT)
+
+/* APB2 peripheral reset register */
+
+#define RCC_APB2RSTR_TIM11RST_BIT 18
+#define RCC_APB2RSTR_TIM10RST_BIT 17
+#define RCC_APB2RSTR_TIM9RST_BIT 16
+#define RCC_APB2RSTR_SYSCFGRST_BIT 14
+#define RCC_APB2RSTR_SPI1RST_BIT 12
+#define RCC_APB2RSTR_SDIORST_BIT 11
+#define RCC_APB2RSTR_ADCRST_BIT 8
+#define RCC_APB2RSTR_USART6RST_BIT 5
+#define RCC_APB2RSTR_USART1RST_BIT 4
+#define RCC_APB2RSTR_TIM8RST_BIT 1
+#define RCC_APB2RSTR_TIM1RST_BIT 0
+
+#define RCC_APB2RSTR_TIM11RST (1U << RCC_APB2RSTR_TIM11RST_BIT)
+#define RCC_APB2RSTR_TIM10RST (1U << RCC_APB2RSTR_TIM10RST_BIT)
+#define RCC_APB2RSTR_TIM9RST (1U << RCC_APB2RSTR_TIM9RST_BIT)
+#define RCC_APB2RSTR_SYSCFGRST (1U << RCC_APB2RSTR_SYSCFGRST_BIT)
+#define RCC_APB2RSTR_SPI1RST (1U << RCC_APB2RSTR_SPI1RST_BIT)
+#define RCC_APB2RSTR_SDIORST (1U << RCC_APB2RSTR_SDIORST_BIT)
+#define RCC_APB2RSTR_ADCRST (1U << RCC_APB2RSTR_ADCRST_BIT)
+#define RCC_APB2RSTR_USART6RST (1U << RCC_APB2RSTR_USART6RST_BIT)
+#define RCC_APB2RSTR_USART1RST (1U << RCC_APB2RSTR_USART1RST_BIT)
+#define RCC_APB2RSTR_TIM8RST (1U << RCC_APB2RSTR_TIM8RST_BIT)
+#define RCC_APB2RSTR_TIM1RST (1U << RCC_APB2RSTR_TIM1RST_BIT)
+
+/* AHB1 peripheral clock enable register */
+
+#define RCC_AHB1ENR_OTGHSULPIEN_BIT 30
+#define RCC_AHB1ENR_OTGHSEN_BIT 29
+#define RCC_AHB1ENR_ETHMACPTPEN_BIT 28
+#define RCC_AHB1ENR_ETHMACRXEN_BIT 27
+#define RCC_AHB1ENR_ETHMACTXEN_BIT 26
+#define RCC_AHB1ENR_ETHMACEN_BIT 25
+#define RCC_AHB1ENR_DMA2EN_BIT 22
+#define RCC_AHB1ENR_DMA1EN_BIT 21
+#define RCC_AHB1ENR_BKPSRAMEN_BIT 18
+#define RCC_AHB1ENR_CRCEN_BIT 12
+#define RCC_AHB1ENR_GPIOIEN_BIT 8
+#define RCC_AHB1ENR_GPIOHEN_BIT 7
+#define RCC_AHB1ENR_GPIOGEN_BIT 6
+#define RCC_AHB1ENR_GPIOFEN_BIT 5
+#define RCC_AHB1ENR_GPIOEEN_BIT 4
+#define RCC_AHB1ENR_GPIODEN_BIT 3
+#define RCC_AHB1ENR_GPIOCEN_BIT 2
+#define RCC_AHB1ENR_GPIOBEN_BIT 1
+#define RCC_AHB1ENR_GPIOAEN_BIT 0
+
+#define RCC_AHB1ENR_OTGHSULPIEN (1U << RCC_AHB1ENR_OTGHSULPIEN_BIT)
+#define RCC_AHB1ENR_OTGHSEN (1U << RCC_AHB1ENR_OTGHSEN_BIT)
+#define RCC_AHB1ENR_ETHMACPTPEN (1U << RCC_AHB1ENR_ETHMACPTPEN_BIT)
+#define RCC_AHB1ENR_ETHMACRXEN (1U << RCC_AHB1ENR_ETHMACRXEN_BIT)
+#define RCC_AHB1ENR_ETHMACTXEN (1U << RCC_AHB1ENR_ETHMACTXEN_BIT)
+#define RCC_AHB1ENR_ETHMACEN (1U << RCC_AHB1ENR_ETHMACEN_BIT)
+#define RCC_AHB1ENR_DMA2EN (1U << RCC_AHB1ENR_DMA2EN_BIT)
+#define RCC_AHB1ENR_DMA1EN (1U << RCC_AHB1ENR_DMA1EN_BIT)
+#define RCC_AHB1ENR_BKPSRAMEN (1U << RCC_AHB1ENR_BKPSRAMEN_BIT)
+#define RCC_AHB1ENR_CRCEN (1U << RCC_AHB1ENR_CRCEN_BIT)
+#define RCC_AHB1ENR_GPIOIEN (1U << RCC_AHB1ENR_GPIOIEN_BIT)
+#define RCC_AHB1ENR_GPIOHEN (1U << RCC_AHB1ENR_GPIOHEN_BIT)
+#define RCC_AHB1ENR_GPIOGEN (1U << RCC_AHB1ENR_GPIOGEN_BIT)
+#define RCC_AHB1ENR_GPIOFEN (1U << RCC_AHB1ENR_GPIOFEN_BIT)
+#define RCC_AHB1ENR_GPIOEEN (1U << RCC_AHB1ENR_GPIOEEN_BIT)
+#define RCC_AHB1ENR_GPIODEN (1U << RCC_AHB1ENR_GPIODEN_BIT)
+#define RCC_AHB1ENR_GPIOCEN (1U << RCC_AHB1ENR_GPIOCEN_BIT)
+#define RCC_AHB1ENR_GPIOBEN (1U << RCC_AHB1ENR_GPIOBEN_BIT)
+#define RCC_AHB1ENR_GPIOAEN (1U << RCC_AHB1ENR_GPIOAEN_BIT)
+
+/* AHB2 peripheral clock enable register */
+
+#define RCC_AHB2ENR_OTGFSEN_BIT 7
+#define RCC_AHB2ENR_RNGEN_BIT 6
+#define RCC_AHB2ENR_HASHEN_BIT 5
+#define RCC_AHB2ENR_CRYPEN_BIT 4
+#define RCC_AHB2ENR_DCMIEN_BIT 0
+
+#define RCC_AHB2ENR_OTGFSEN (1U << RCC_AHB2ENR_OTGFSEN_BIT)
+#define RCC_AHB2ENR_RNGEN (1U << RCC_AHB2ENR_RNGEN_BIT)
+#define RCC_AHB2ENR_HASHEN (1U << RCC_AHB2ENR_HASHEN_BIT)
+#define RCC_AHB2ENR_CRYPEN (1U << RCC_AHB2ENR_CRYPEN_BIT)
+#define RCC_AHB2ENR_DCMIEN (1U << RCC_AHB2ENR_DCMIEN_BIT)
+
+/* AHB3 peripheral clock enable register */
+
+#define RCC_AHB3ENR_FSMCEN_BIT 0
+
+#define RCC_AHB3ENR_FSMCEN (1U << RCC_AHB3ENR_FSMCEN_BIT)
+
+/* APB1 peripheral clock enable register */
+
+#define RCC_APB1ENR_DACEN_BIT 29
+#define RCC_APB1ENR_PWREN_BIT 28
+#define RCC_APB1ENR_CAN2EN_BIT 26
+#define RCC_APB1ENR_CAN1EN_BIT 25
+#define RCC_APB1ENR_I2C3EN_BIT 23
+#define RCC_APB1ENR_I2C2EN_BIT 22
+#define RCC_APB1ENR_I2C1EN_BIT 21
+#define RCC_APB1ENR_UART5EN_BIT 20
+#define RCC_APB1ENR_UART4EN_BIT 19
+#define RCC_APB1ENR_USART3EN_BIT 18
+#define RCC_APB1ENR_USART2EN_BIT 17
+#define RCC_APB1ENR_SPI3EN_BIT 15
+#define RCC_APB1ENR_SPI2EN_BIT 14
+#define RCC_APB1ENR_WWDGEN_BIT 11
+#define RCC_APB1ENR_TIM14EN_BIT 8
+#define RCC_APB1ENR_TIM13EN_BIT 7
+#define RCC_APB1ENR_TIM12EN_BIT 6
+#define RCC_APB1ENR_TIM7EN_BIT 5
+#define RCC_APB1ENR_TIM6EN_BIT 4
+#define RCC_APB1ENR_TIM5EN_BIT 3
+#define RCC_APB1ENR_TIM4EN_BIT 2
+#define RCC_APB1ENR_TIM3EN_BIT 1
+#define RCC_APB1ENR_TIM2EN_BIT 0
+
+#define RCC_APB1ENR_DACEN (1U << RCC_APB1ENR_DACEN_BIT)
+#define RCC_APB1ENR_PWREN (1U << RCC_APB1ENR_PWREN_BIT)
+#define RCC_APB1ENR_CAN2EN (1U << RCC_APB1ENR_CAN2EN_BIT)
+#define RCC_APB1ENR_CAN1EN (1U << RCC_APB1ENR_CAN1EN_BIT)
+#define RCC_APB1ENR_I2C3EN (1U << RCC_APB1ENR_I2C3EN_BIT)
+#define RCC_APB1ENR_I2C2EN (1U << RCC_APB1ENR_I2C2EN_BIT)
+#define RCC_APB1ENR_I2C1EN (1U << RCC_APB1ENR_I2C1EN_BIT)
+#define RCC_APB1ENR_UART5EN (1U << RCC_APB1ENR_UART5EN_BIT)
+#define RCC_APB1ENR_UART4EN (1U << RCC_APB1ENR_UART4EN_BIT)
+#define RCC_APB1ENR_USART3EN (1U << RCC_APB1ENR_USART3EN_BIT)
+#define RCC_APB1ENR_USART2EN (1U << RCC_APB1ENR_USART2EN_BIT)
+#define RCC_APB1ENR_SPI3EN (1U << RCC_APB1ENR_SPI3EN_BIT)
+#define RCC_APB1ENR_SPI2EN (1U << RCC_APB1ENR_SPI2EN_BIT)
+#define RCC_APB1ENR_WWDGEN (1U << RCC_APB1ENR_WWDGEN_BIT)
+#define RCC_APB1ENR_TIM14EN (1U << RCC_APB1ENR_TIM14EN_BIT)
+#define RCC_APB1ENR_TIM13EN (1U << RCC_APB1ENR_TIM13EN_BIT)
+#define RCC_APB1ENR_TIM12EN (1U << RCC_APB1ENR_TIM12EN_BIT)
+#define RCC_APB1ENR_TIM7EN (1U << RCC_APB1ENR_TIM7EN_BIT)
+#define RCC_APB1ENR_TIM6EN (1U << RCC_APB1ENR_TIM6EN_BIT)
+#define RCC_APB1ENR_TIM5EN (1U << RCC_APB1ENR_TIM5EN_BIT)
+#define RCC_APB1ENR_TIM4EN (1U << RCC_APB1ENR_TIM4EN_BIT)
+#define RCC_APB1ENR_TIM3EN (1U << RCC_APB1ENR_TIM3EN_BIT)
+#define RCC_APB1ENR_TIM2EN (1U << RCC_APB1ENR_TIM2EN_BIT)
+
+/* APB2 peripheral clock enable register */
+
+#define RCC_APB2ENR_TIM11EN_BIT 18
+#define RCC_APB2ENR_TIM10EN_BIT 17
+#define RCC_APB2ENR_TIM9EN_BIT 16
+#define RCC_APB2ENR_SYSCFGEN_BIT 14
+#define RCC_APB2ENR_SPI1EN_BIT 12
+#define RCC_APB2ENR_SDIOEN_BIT 11
+#define RCC_APB2ENR_ADC3EN_BIT 10
+#define RCC_APB2ENR_ADC2EN_BIT 9
+#define RCC_APB2ENR_ADC1EN_BIT 8
+#define RCC_APB2ENR_USART6EN_BIT 5
+#define RCC_APB2ENR_USART1EN_BIT 4
+#define RCC_APB2ENR_TIM8EN_BIT 1
+#define RCC_APB2ENR_TIM1EN_BIT 0
+
+#define RCC_APB2ENR_TIM11EN (1U << RCC_APB2ENR_TIM11EN_BIT)
+#define RCC_APB2ENR_TIM10EN (1U << RCC_APB2ENR_TIM10EN_BIT)
+#define RCC_APB2ENR_TIM9EN (1U << RCC_APB2ENR_TIM9EN_BIT)
+#define RCC_APB2ENR_SYSCFGEN (1U << RCC_APB2ENR_SYSCFGEN_BIT)
+#define RCC_APB2ENR_SPI1EN (1U << RCC_APB2ENR_SPI1EN_BIT)
+#define RCC_APB2ENR_SDIOEN (1U << RCC_APB2ENR_SDIOEN_BIT)
+#define RCC_APB2ENR_ADC3EN (1U << RCC_APB2ENR_ADC3EN_BIT)
+#define RCC_APB2ENR_ADC2EN (1U << RCC_APB2ENR_ADC2EN_BIT)
+#define RCC_APB2ENR_ADC1EN (1U << RCC_APB2ENR_ADC1EN_BIT)
+#define RCC_APB2ENR_USART6EN (1U << RCC_APB2ENR_USART6EN_BIT)
+#define RCC_APB2ENR_USART1EN (1U << RCC_APB2ENR_USART1EN_BIT)
+#define RCC_APB2ENR_TIM8EN (1U << RCC_APB2ENR_TIM8EN_BIT)
+#define RCC_APB2ENR_TIM1EN (1U << RCC_APB2ENR_TIM1EN_BIT)
+
+/* AHB1 peripheral clock enable in low power mode register */
+
+#define RCC_AHB1LPENR_OTGHSULPILPEN_BIT 30
+#define RCC_AHB1LPENR_OTGHSLPEN_BIT 29
+#define RCC_AHB1LPENR_ETHMACPTPLPEN_BIT 28
+#define RCC_AHB1LPENR_ETHMACRXLPEN_BIT 27
+#define RCC_AHB1LPENR_ETHMACTXLPEN_BIT 26
+#define RCC_AHB1LPENR_ETHMACLPEN_BIT 25
+#define RCC_AHB1LPENR_DMA2LPEN_BIT 22
+#define RCC_AHB1LPENR_DMA1LPEN_BIT 21
+#define RCC_AHB1LPENR_BKPSRAMLPEN_BIT 18
+#define RCC_AHB1LPENR_SRAM2LPEN_BIT 17
+#define RCC_AHB1LPENR_SRAM1LPEN_BIT 16
+#define RCC_AHB1LPENR_FLITFLPEN_BIT 15
+#define RCC_AHB1LPENR_CRCLPEN_BIT 12
+#define RCC_AHB1LPENR_GPIOILPEN_BIT 8
+#define RCC_AHB1LPENR_GPIOGLPEN_BIT 6
+#define RCC_AHB1LPENR_GPIOFLPEN_BIT 5
+#define RCC_AHB1LPENR_GPIOELPEN_BIT 4
+#define RCC_AHB1LPENR_GPIODLPEN_BIT 3
+#define RCC_AHB1LPENR_GPIOCLPEN_BIT 2
+#define RCC_AHB1LPENR_GPIOBLPEN_BIT 1
+#define RCC_AHB1LPENR_GPIOALPEN_BIT 0
+
+#define RCC_AHB1LPENR_OTGHSULPILPEN (1U << RCC_AHB1LPENR_OTGHSULPILPEN_BIT)
+#define RCC_AHB1LPENR_OTGHSLPEN (1U << RCC_AHB1LPENR_OTGHSLPEN_BIT)
+#define RCC_AHB1LPENR_ETHMACPTPLPEN (1U << RCC_AHB1LPENR_ETHMACPTPLPEN_BIT)
+#define RCC_AHB1LPENR_ETHMACRXLPEN (1U << RCC_AHB1LPENR_ETHMACRXLPEN_BIT)
+#define RCC_AHB1LPENR_ETHMACTXLPEN (1U << RCC_AHB1LPENR_ETHMACTXLPEN_BIT)
+#define RCC_AHB1LPENR_ETHMACLPEN (1U << RCC_AHB1LPENR_ETHMACLPEN_BIT)
+#define RCC_AHB1LPENR_DMA2LPEN (1U << RCC_AHB1LPENR_DMA2LPEN_BIT)
+#define RCC_AHB1LPENR_DMA1LPEN (1U << RCC_AHB1LPENR_DMA1LPEN_BIT)
+#define RCC_AHB1LPENR_BKPSRAMLPEN (1U << RCC_AHB1LPENR_BKPSRAMLPEN_BIT)
+#define RCC_AHB1LPENR_SRAM2LPEN (1U << RCC_AHB1LPENR_SRAM2LPEN_BIT)
+#define RCC_AHB1LPENR_SRAM1LPEN (1U << RCC_AHB1LPENR_SRAM1LPEN_BIT)
+#define RCC_AHB1LPENR_FLITFLPEN (1U << RCC_AHB1LPENR_FLITFLPEN_BIT)
+#define RCC_AHB1LPENR_CRCLPEN (1U << RCC_AHB1LPENR_CRCLPEN_BIT)
+#define RCC_AHB1LPENR_GPIOILPEN (1U << RCC_AHB1LPENR_GPIOILPEN_BIT)
+#define RCC_AHB1LPENR_GPIOGLPEN (1U << RCC_AHB1LPENR_GPIOGLPEN_BIT)
+#define RCC_AHB1LPENR_GPIOFLPEN (1U << RCC_AHB1LPENR_GPIOFLPEN_BIT)
+#define RCC_AHB1LPENR_GPIOELPEN (1U << RCC_AHB1LPENR_GPIOELPEN_BIT)
+#define RCC_AHB1LPENR_GPIODLPEN (1U << RCC_AHB1LPENR_GPIODLPEN_BIT)
+#define RCC_AHB1LPENR_GPIOCLPEN (1U << RCC_AHB1LPENR_GPIOCLPEN_BIT)
+#define RCC_AHB1LPENR_GPIOBLPEN (1U << RCC_AHB1LPENR_GPIOBLPEN_BIT)
+#define RCC_AHB1LPENR_GPIOALPEN (1U << RCC_AHB1LPENR_GPIOALPEN_BIT)
+
+/* AHB2 peripheral clock enable in low power mode register */
+
+#define RCC_AHB2LPENR_OTGFSLPEN_BIT 7
+#define RCC_AHB2LPENR_RNGLPEN_BIT 6
+#define RCC_AHB2LPENR_HASHLPEN_BIT 5
+#define RCC_AHB2LPENR_CRYPLPEN_BIT 4
+#define RCC_AHB2LPENR_DCMILPEN_BIT 0
+
+#define RCC_AHB2LPENR_OTGFSLPEN (1U << RCC_AHB2LPENR_OTGFSLPEN_BIT)
+#define RCC_AHB2LPENR_RNGLPEN (1U << RCC_AHB2LPENR_RNGLPEN_BIT)
+#define RCC_AHB2LPENR_HASHLPEN (1U << RCC_AHB2LPENR_HASHLPEN_BIT)
+#define RCC_AHB2LPENR_CRYPLPEN (1U << RCC_AHB2LPENR_CRYPLPEN_BIT)
+#define RCC_AHB2LPENR_DCMILPEN (1U << RCC_AHB2LPENR_DCMILPEN_BIT)
+
+/* AHB3 peripheral clock enable in low power mode register */
+
+#define RCC_AHB3LPENR_FSMCLPEN_BIT 0
+
+#define RCC_AHB3LPENR_FSMCLPEN (1U << RCC_AHB3LPENR_FSMCLPEN_BIT)
+
+/* APB1 peripheral clock enable in low power mode register */
+
+#define RCC_APB1LPENR_DACLPEN_BIT 29
+#define RCC_APB1LPENR_PWRLPEN_BIT 28
+#define RCC_APB1LPENR_CAN2LPEN_BIT 26
+#define RCC_APB1LPENR_CAN1LPEN_BIT 25
+#define RCC_APB1LPENR_I2C3LPEN_BIT 23
+#define RCC_APB1LPENR_I2C2LPEN_BIT 22
+#define RCC_APB1LPENR_I2C1LPEN_BIT 21
+#define RCC_APB1LPENR_UART5LPEN_BIT 20
+#define RCC_APB1LPENR_UART4LPEN_BIT 19
+#define RCC_APB1LPENR_USART3LPEN_BIT 18
+#define RCC_APB1LPENR_USART2LPEN_BIT 17
+#define RCC_APB1LPENR_SPI3LPEN_BIT 15
+#define RCC_APB1LPENR_SPI2LPEN_BIT 14
+#define RCC_APB1LPENR_WWDGLPEN_BIT 11
+#define RCC_APB1LPENR_TIM14LPEN_BIT 8
+#define RCC_APB1LPENR_TIM13LPEN_BIT 7
+#define RCC_APB1LPENR_TIM12LPEN_BIT 6
+#define RCC_APB1LPENR_TIM7LPEN_BIT 5
+#define RCC_APB1LPENR_TIM6LPEN_BIT 4
+#define RCC_APB1LPENR_TIM5LPEN_BIT 3
+#define RCC_APB1LPENR_TIM4LPEN_BIT 2
+#define RCC_APB1LPENR_TIM3LPEN_BIT 1
+#define RCC_APB1LPENR_TIM2LPEN_BIT 0
+
+#define RCC_APB1LPENR_DACLPEN (1U << RCC_APB1LPENR_DACLPEN_BIT)
+#define RCC_APB1LPENR_PWRLPEN (1U << RCC_APB1LPENR_PWRLPEN_BIT)
+#define RCC_APB1LPENR_CAN2LPEN (1U << RCC_APB1LPENR_CAN2LPEN_BIT)
+#define RCC_APB1LPENR_CAN1LPEN (1U << RCC_APB1LPENR_CAN1LPEN_BIT)
+#define RCC_APB1LPENR_I2C3LPEN (1U << RCC_APB1LPENR_I2C3LPEN_BIT)
+#define RCC_APB1LPENR_I2C2LPEN (1U << RCC_APB1LPENR_I2C2LPEN_BIT)
+#define RCC_APB1LPENR_I2C1LPEN (1U << RCC_APB1LPENR_I2C1LPEN_BIT)
+#define RCC_APB1LPENR_UART5LPEN (1U << RCC_APB1LPENR_UART5LPEN_BIT)
+#define RCC_APB1LPENR_UART4LPEN (1U << RCC_APB1LPENR_UART4LPEN_BIT)
+#define RCC_APB1LPENR_USART3LPEN (1U << RCC_APB1LPENR_USART3LPEN_BIT)
+#define RCC_APB1LPENR_USART2LPEN (1U << RCC_APB1LPENR_USART2LPEN_BIT)
+#define RCC_APB1LPENR_SPI3LPEN (1U << RCC_APB1LPENR_SPI3LPEN_BIT)
+#define RCC_APB1LPENR_SPI2LPEN (1U << RCC_APB1LPENR_SPI2LPEN_BIT)
+#define RCC_APB1LPENR_WWDGLPEN (1U << RCC_APB1LPENR_WWDGLPEN_BIT)
+#define RCC_APB1LPENR_TIM14LPEN (1U << RCC_APB1LPENR_TIM14LPEN_BIT)
+#define RCC_APB1LPENR_TIM13LPEN (1U << RCC_APB1LPENR_TIM13LPEN_BIT)
+#define RCC_APB1LPENR_TIM12LPEN (1U << RCC_APB1LPENR_TIM12LPEN_BIT)
+#define RCC_APB1LPENR_TIM7LPEN (1U << RCC_APB1LPENR_TIM7LPEN_BIT)
+#define RCC_APB1LPENR_TIM6LPEN (1U << RCC_APB1LPENR_TIM6LPEN_BIT)
+#define RCC_APB1LPENR_TIM5LPEN (1U << RCC_APB1LPENR_TIM5LPEN_BIT)
+#define RCC_APB1LPENR_TIM4LPEN (1U << RCC_APB1LPENR_TIM4LPEN_BIT)
+#define RCC_APB1LPENR_TIM3LPEN (1U << RCC_APB1LPENR_TIM3LPEN_BIT)
+#define RCC_APB1LPENR_TIM2LPEN (1U << RCC_APB1LPENR_TIM2LPEN_BIT)
+
+/* APB2 peripheral clock enable in low power mode register */
+
+#define RCC_APB2LPENR_TIM11LPEN_BIT 18
+#define RCC_APB2LPENR_TIM10LPEN_BIT 17
+#define RCC_APB2LPENR_TIM9LPEN_BIT 16
+#define RCC_APB2LPENR_SYSCFGLPEN_BIT 14
+#define RCC_APB2LPENR_SPI1LPEN_BIT 12
+#define RCC_APB2LPENR_SDIOLPEN_BIT 11
+#define RCC_APB2LPENR_ADC3LPEN_BIT 10
+#define RCC_APB2LPENR_ADC2LPEN_BIT 9
+#define RCC_APB2LPENR_ADC1LPEN_BIT 8
+#define RCC_APB2LPENR_USART6LPEN_BIT 5
+#define RCC_APB2LPENR_USART1LPEN_BIT 4
+#define RCC_APB2LPENR_TIM8LPEN_BIT 1
+#define RCC_APB2LPENR_TIM1LPEN_BIT 0
+
+#define RCC_APB2LPENR_TIM11LPEN (1U << RCC_APB2LPENR_TIM11LPEN_BIT)
+#define RCC_APB2LPENR_TIM10LPEN (1U << RCC_APB2LPENR_TIM10LPEN_BIT)
+#define RCC_APB2LPENR_TIM9LPEN (1U << RCC_APB2LPENR_TIM9LPEN_BIT)
+#define RCC_APB2LPENR_SYSCFGLPEN (1U << RCC_APB2LPENR_SYSCFGLPEN_BIT)
+#define RCC_APB2LPENR_SPI1LPEN (1U << RCC_APB2LPENR_SPI1LPEN_BIT)
+#define RCC_APB2LPENR_SDIOLPEN (1U << RCC_APB2LPENR_SDIOLPEN_BIT)
+#define RCC_APB2LPENR_ADC3LPEN (1U << RCC_APB2LPENR_ADC3LPEN_BIT)
+#define RCC_APB2LPENR_ADC2LPEN (1U << RCC_APB2LPENR_ADC2LPEN_BIT)
+#define RCC_APB2LPENR_ADC1LPEN (1U << RCC_APB2LPENR_ADC1LPEN_BIT)
+#define RCC_APB2LPENR_USART6LPEN (1U << RCC_APB2LPENR_USART6LPEN_BIT)
+#define RCC_APB2LPENR_USART1LPEN (1U << RCC_APB2LPENR_USART1LPEN_BIT)
+#define RCC_APB2LPENR_TIM8LPEN (1U << RCC_APB2LPENR_TIM8LPEN_BIT)
+#define RCC_APB2LPENR_TIM1LPEN (1U << RCC_APB2LPENR_TIM1LPEN_BIT)
+
+/* Backup domain control register */
+
+#define RCC_BDCR_BDRST_BIT 16
+#define RCC_BDCR_RTCEN_BIT 15
+#define RCC_BDCR_LSEBYP_BIT 2
+#define RCC_BDCR_LSERDY_BIT 1
+#define RCC_BDCR_LSEON_BIT 0
+
+#define RCC_BDCR_BDRST (1U << RCC_BDCR_BDRST_BIT)
+#define RCC_BDCR_RTCEN (1U << RCC_BDCR_RTCEN_BIT)
+#define RCC_BDCR_RTCSEL (0x3 << 8)
+#define RCC_BDCR_RTCSEL_NOCLOCK (0x0 << 8)
+#define RCC_BDCR_RTCSEL_LSE (0x1 << 8)
+#define RCC_BDCR_RTCSEL_LSI (0x2 << 8)
+#define RCC_BDCR_RTCSEL_HSE_DIV (0x3 << 8)
+#define RCC_BDCR_LSEBYP (1U << RCC_BDCR_LSEBYP_BIT)
+#define RCC_BDCR_LSERDY (1U << RCC_BDCR_LSERDY_BIT)
+#define RCC_BDCR_LSEON (1U << RCC_BDCR_LSEON_BIT)
+
+/* Clock control and status register */
+
+#define RCC_CSR_LPWRRSTF_BIT 31
+#define RCC_CSR_WWDGRSTF_BIT 30
+#define RCC_CSR_IWDGRSTF_BIT 29
+#define RCC_CSR_SFTRSTF_BIT 28
+#define RCC_CSR_PORRSTF_BIT 27
+#define RCC_CSR_PINRSTF_BIT 26
+#define RCC_CSR_BORRSTF_BIT 25
+#define RCC_CSR_RMVF_BIT 24
+#define RCC_CSR_LSIRDY_BIT 1
+#define RCC_CSR_LSION_BIT 0
+
+#define RCC_CSR_LPWRRSTF (1U << RCC_CSR_LPWRRSTF_BIT)
+#define RCC_CSR_WWDGRSTF (1U << RCC_CSR_WWDGRSTF_BIT)
+#define RCC_CSR_IWDGRSTF (1U << RCC_CSR_IWDGRSTF_BIT)
+#define RCC_CSR_SFTRSTF (1U << RCC_CSR_SFTRSTF_BIT)
+#define RCC_CSR_PORRSTF (1U << RCC_CSR_PORRSTF_BIT)
+#define RCC_CSR_PINRSTF (1U << RCC_CSR_PINRSTF_BIT)
+#define RCC_CSR_BORRSTF (1U << RCC_CSR_BORRSTF_BIT)
+#define RCC_CSR_RMVF (1U << RCC_CSR_RMVF_BIT)
+#define RCC_CSR_LSIRDY (1U << RCC_CSR_LSIRDY_BIT)
+#define RCC_CSR_LSION (1U << RCC_CSR_LSION_BIT)
+
+/* Spread spectrum clock generation register */
+
+#define RCC_SSCGR_SSCGEN_BIT 31
+#define RCC_SSCGR_SPREADSEL_BIT 30
+
+#define RCC_SSCGR_SSCGEN (1U << RCC_SSCGR_SSCGEN_BIT)
+#define RCC_SSCGR_SPREADSEL (1U << RCC_SSCGR_SPREADSEL_BIT)
+#define RCC_SSCGR_SPREADSEL_CENTER (0x0 << RCC_SSCGR_SPREADSEL_BIT)
+#define RCC_SSCGR_SPREADSEL_DOWN (0x1 << RCC_SSCGR_SPREADSEL_BIT)
+#define RCC_SSCGR_INCSTEP (0xFFF << 16)
+#define RCC_SSCGR_MODPER 0xFFFF
+
+/* PLLI2S configuration register */
+
+#define RCC_PLLI2SCFGR_PLLI2SR (0x7 << 28)
+#define RCC_PLLI2SCFGR_PLLI2SN (0x1FF << 6)
+
+/*
+ * Clock sources, domains, and peripheral clock IDs.
+ */
+
+/**
+ * @brief STM32F2 clock sources.
+ */
+typedef enum rcc_clk {
+ RCC_CLK_PLLI2S = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) |
+ RCC_CR_PLLI2SON_BIT), /**< Dedicated PLL
+ for I2S. */
+ RCC_CLK_PLL = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) |
+ RCC_CR_PLLON_BIT), /**< Main PLL, clocked by
+ HSI or HSE. */
+ RCC_CLK_HSE = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) |
+ RCC_CR_HSEON_BIT), /**< High speed external. */
+ RCC_CLK_HSI = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) |
+ RCC_CR_HSION_BIT), /**< High speed internal. */
+ RCC_CLK_LSE = (uint16)((offsetof(struct rcc_reg_map, BDCR) << 8) |
+ RCC_BDCR_LSEON_BIT), /**< Low-speed external
+ * (32.768 KHz). */
+ RCC_CLK_LSI = (uint16)((offsetof(struct rcc_reg_map, CSR) << 8) |
+ RCC_CSR_LSION_BIT), /**< Low-speed internal
+ * (approximately 32 KHz). */
+} rcc_clk;
+
+/**
+ * @brief STM32F2 rcc_clk_id.
+ */
+typedef enum rcc_clk_id {
+ RCC_ADC1,
+ RCC_ADC2,
+ RCC_ADC3,
+ RCC_BKPSRAM,
+ RCC_CAN1,
+ RCC_CAN2,
+ RCC_CRC,
+ RCC_CRYP,
+ RCC_DAC,
+ RCC_DCMI,
+ RCC_DMA1,
+ RCC_DMA2,
+ RCC_ETHMAC,
+ RCC_ETHMACPTP,
+ RCC_ETHMACRX,
+ RCC_ETHMACTX,
+ RCC_FSMC,
+ RCC_GPIOA,
+ RCC_GPIOB,
+ RCC_GPIOC,
+ RCC_GPIOD,
+ RCC_GPIOE,
+ RCC_GPIOF,
+ RCC_GPIOG,
+ RCC_GPIOH,
+ RCC_GPIOI,
+ RCC_HASH,
+ RCC_I2C1,
+ RCC_I2C2,
+ RCC_I2C3,
+ RCC_OTGFS,
+ RCC_OTGHS,
+ RCC_OTGHSULPI,
+ RCC_PWR,
+ RCC_RNG,
+ RCC_SDIO,
+ RCC_SPI1,
+ RCC_SPI2,
+ RCC_SPI3,
+ RCC_SYSCFG,
+ RCC_TIMER1,
+ RCC_TIMER10,
+ RCC_TIMER11,
+ RCC_TIMER12,
+ RCC_TIMER13,
+ RCC_TIMER14,
+ RCC_TIMER2,
+ RCC_TIMER3,
+ RCC_TIMER4,
+ RCC_TIMER5,
+ RCC_TIMER6,
+ RCC_TIMER7,
+ RCC_TIMER8,
+ RCC_TIMER9,
+ RCC_USART1,
+ RCC_USART2,
+ RCC_USART3,
+ RCC_UART4,
+ RCC_UART5,
+ RCC_USART6,
+ RCC_WWDG,
+} rcc_clk_id;
+
+/**
+ * @brief STM32F2 PLL entry clock source
+ * @see rcc_configure_pll()
+ */
+typedef enum rcc_pllsrc {
+ RCC_PLLSRC_HSI = 0,
+ RCC_PLLSRC_HSE = RCC_PLLCFGR_PLLSRC,
+} rcc_pllsrc;
+
+/**
+ * @brief STM32F2 Peripheral clock domains.
+ */
+typedef enum rcc_clk_domain {
+ RCC_APB1,
+ RCC_APB2,
+ RCC_AHB1,
+ RCC_AHB2,
+ RCC_AHB3,
+} rcc_clk_domain;
+
+/*
+ * Prescalers and dividers.
+ */
+
+/**
+ * @brief STM32F2 Prescaler identifiers.
+ */
+typedef enum rcc_prescaler {
+ RCC_PRESCALER_MCO2,
+ RCC_PRESCALER_MCO1,
+ RCC_PRESCALER_RTC,
+ RCC_PRESCALER_APB2,
+ RCC_PRESCALER_APB1,
+ RCC_PRESCALER_AHB
+} rcc_prescaler;
+
+/**
+ * @brief STM32F2 MCO2 prescaler dividers.
+ */
+typedef enum rcc_mco2_divider {
+ RCC_MCO2_DIV_1 = RCC_CFGR_MCO2PRE_DIV_1,
+ RCC_MCO2_DIV_2 = RCC_CFGR_MCO2PRE_DIV_2,
+ RCC_MCO2_DIV_3 = RCC_CFGR_MCO2PRE_DIV_3,
+ RCC_MCO2_DIV_4 = RCC_CFGR_MCO2PRE_DIV_4,
+ RCC_MCO2_DIV_5 = RCC_CFGR_MCO2PRE_DIV_5,
+} rcc_mco2_divider;
+
+/**
+ * @brief STM32F2 MCO1 prescaler dividers.
+ */
+typedef enum rcc_mco1_divider {
+ RCC_MCO1_DIV_1 = RCC_CFGR_MCO1PRE_DIV_1,
+ RCC_MCO1_DIV_2 = RCC_CFGR_MCO1PRE_DIV_2,
+ RCC_MCO1_DIV_3 = RCC_CFGR_MCO1PRE_DIV_3,
+ RCC_MCO1_DIV_4 = RCC_CFGR_MCO1PRE_DIV_4,
+ RCC_MCO1_DIV_5 = RCC_CFGR_MCO1PRE_DIV_5,
+} rcc_mco1_divider;
+
+/**
+ * @brief STM32F2 RTC prescaler dividers.
+ */
+typedef enum rcc_rtc_divider { /* FIXME [0.0.13] TODO */
+ RCC_RTC_DIV_TODO = 0xFFFFFFFF,
+} rcc_rtc_divider;
+
+/**
+ * @brief STM32F2 AP2 prescaler dividers.
+ */
+typedef enum rcc_apb2_divider {
+ RCC_APB2_HCLK_DIV_1 = 0,
+ RCC_APB2_HCLK_DIV_2 = RCC_CFGR_PPRE2_AHB_DIV_2,
+ RCC_APB2_HCLK_DIV_4 = RCC_CFGR_PPRE2_AHB_DIV_4,
+ RCC_APB2_HCLK_DIV_8 = RCC_CFGR_PPRE2_AHB_DIV_8,
+ RCC_APB2_HCLK_DIV_16 = RCC_CFGR_PPRE2_AHB_DIV_16,
+} rcc_apb2_divider;
+
+/**
+ * @brief STM32F2 APB1 prescaler dividers.
+ */
+typedef enum rcc_apb1_divider {
+ RCC_APB1_HCLK_DIV_1 = 0,
+ RCC_APB1_HCLK_DIV_2 = RCC_CFGR_PPRE1_AHB_DIV_2,
+ RCC_APB1_HCLK_DIV_4 = RCC_CFGR_PPRE1_AHB_DIV_4,
+ RCC_APB1_HCLK_DIV_8 = RCC_CFGR_PPRE1_AHB_DIV_8,
+ RCC_APB1_HCLK_DIV_16 = RCC_CFGR_PPRE1_AHB_DIV_16,
+} rcc_apb1_divider;
+
+/**
+ * @brief STM32F2 AHB prescaler dividers.
+ */
+typedef enum rcc_ahb_divider {
+ RCC_AHB_SYSCLK_DIV_1 = 0,
+ RCC_AHB_SYSCLK_DIV_2 = RCC_CFGR_HPRE_SYSCLK_DIV_2,
+ RCC_AHB_SYSCLK_DIV_4 = RCC_CFGR_HPRE_SYSCLK_DIV_4,
+ RCC_AHB_SYSCLK_DIV_8 = RCC_CFGR_HPRE_SYSCLK_DIV_8,
+ RCC_AHB_SYSCLK_DIV_16 = RCC_CFGR_HPRE_SYSCLK_DIV_16,
+ RCC_AHB_SYSCLK_DIV_64 = RCC_CFGR_HPRE_SYSCLK_DIV_64,
+ RCC_AHB_SYSCLK_DIV_128 = RCC_CFGR_HPRE_SYSCLK_DIV_128,
+ RCC_AHB_SYSCLK_DIV_256 = RCC_CFGR_HPRE_SYSCLK_DIV_256,
+ RCC_AHB_SYSCLK_DIV_512 = RCC_CFGR_HPRE_SYSCLK_DIV_512,
+} rcc_ahb_divider;
+
+/**
+ * @brief STM32F2 PLL configuration values.
+ * Point to one of these with the "data" field in a struct rcc_pll_cfg.
+ * @see struct rcc_pll_cfg.
+ */
+typedef struct stm32f2_rcc_pll_data {
+ uint8 pllq; /**<
+ * @brief PLLQ value.
+ * Allowed values: 4, 5, ..., 15. */
+ uint8 pllp; /**<
+ * @brief PLLP value.
+ * Allowed values: 2, 4, 6, 8. */
+ uint16 plln; /**<
+ * @brief PLLN value.
+ * Allowed values: 192, 193, ..., 432. */
+ uint8 pllm; /**<
+ * @brief PLLM value.
+ * Allowed values: 2, 3, ..., 63. */
+} stm32f2_rcc_pll_data;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmaple/stm32f2-f4/include/series/spi.h b/libmaple/stm32f2-f4/include/series/spi.h
new file mode 100644
index 0000000..7b9f94a
--- /dev/null
+++ b/libmaple/stm32f2-f4/include/series/spi.h
@@ -0,0 +1,88 @@
+/******************************************************************************
+ * 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/spi.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F2 SPI/I2S series header.
+ */
+
+#ifndef _LIBMAPLE_STM32F2_SPI_H_
+#define _LIBMAPLE_STM32F2_SPI_H_
+
+#include <libmaple/gpio.h> /* for gpio_af */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Register map base pointers
+ */
+
+struct spi_reg_map;
+
+#define SPI1_BASE ((struct spi_reg_map*)0x40013000)
+#define SPI2_BASE ((struct spi_reg_map*)0x40003800)
+#define SPI3_BASE ((struct spi_reg_map*)0x40003C00)
+
+/*
+ * Register bit definitions
+ */
+
+/* Control register 2 */
+
+#define SPI_CR2_FRF_BIT 4
+
+#define SPI_CR2_FRF (1U << SPI_CR2_FRF_BIT)
+
+/* Status register */
+
+#define SPI_SR_TIFRFE_BIT 8
+
+#define SPI_SR_TIFRFE (1U << SPI_SR_TIFRFE_BIT)
+
+/*
+ * Device pointers
+ */
+
+struct spi_dev;
+
+extern struct spi_dev *SPI1;
+extern struct spi_dev *SPI2;
+extern struct spi_dev *SPI3;
+
+/*
+ * Routines
+ */
+
+gpio_af spi_get_af(struct spi_dev *dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmaple/stm32f2-f4/include/series/stm32.h b/libmaple/stm32f2-f4/include/series/stm32.h
new file mode 100644
index 0000000..c2ad2f2
--- /dev/null
+++ b/libmaple/stm32f2-f4/include/series/stm32.h
@@ -0,0 +1,109 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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/stm32.h
+ * @brief STM32F2 chip- and series-specific definitions.
+ */
+
+#ifndef _LIBMAPLE_STM32F2_STM32_H_
+#define _LIBMAPLE_STM32F2_STM32_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * MCU-specific values
+ */
+
+#if defined(MCU_STM32F207IC) || defined(MCU_STM32F207IG)
+# define STM32_MCU_SERIES STM32_SERIES_F2
+# define STM32_NR_GPIO_PORTS 9
+# define STM32_TIMER_MASK 0x7FFE /* TIMER1-TIMER14. */
+# define STM32_SRAM_END ((void*)0x20020000)
+#elif defined(MCU_STM32F401VC)
+# define STM32_MCU_SERIES STM32_SERIES_F4
+# define STM32_NR_GPIO_PORTS 5
+# define STM32_TIMER_MASK 0x3E
+/* TODO: This value for STM32_SRAM_END is very generous */
+# define STM32_SRAM_END ((void*)0x20020000)
+#elif defined(MCU_STM32F401CC)
+# define STM32_MCU_SERIES STM32_SERIES_F4
+# define STM32_NR_GPIO_PORTS 3
+# define STM32_TIMER_MASK 0x3E
+# define STM32_SRAM_END ((void*)0x20010000)
+#else
+#warning "Unsupported or unspecified STM32F2 MCU."
+#endif
+
+/*
+ * Series-specific values
+ */
+
+#if STM32_MCU_SERIES == STM32_SERIES_F2
+# define STM32_NR_INTERRUPTS 81
+# define STM32_HAVE_FSMC 1
+# define STM32_HAVE_USB 1
+# define STM32_HAVE_DAC 1
+
+# ifndef STM32_PCLK1
+# define STM32_PCLK1 30000000U
+# endif
+
+# ifndef STM32_PCLK2
+# define STM32_PCLK2 60000000U
+# endif
+
+# ifndef STM32_DELAY_US_MULT
+# define STM32_DELAY_US_MULT 20 /* FIXME: dummy value. */
+# endif
+#elif STM32_MCU_SERIES == STM32_SERIES_F4
+# define STM32_NR_INTERRUPTS 84
+# define STM32_HAVE_FSMC 0
+# define STM32_HAVE_USB 0
+# define STM32_HAVE_DAC 0
+
+#ifndef STM32_PCLK1
+#define STM32_PCLK1 42000000U
+#endif
+
+#ifndef STM32_PCLK2
+#define STM32_PCLK2 84000000U
+#endif
+
+#ifndef STM32_DELAY_US_MULT
+#define STM32_DELAY_US_MULT 28 /* CYCLES_PER_MICROSECOND/3 */
+#endif
+#else
+# error "Invalid STM32 series for this header"
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmaple/stm32f2-f4/include/series/timer.h b/libmaple/stm32f2-f4/include/series/timer.h
new file mode 100644
index 0000000..a7ac276
--- /dev/null
+++ b/libmaple/stm32f2-f4/include/series/timer.h
@@ -0,0 +1,176 @@
+/******************************************************************************
+ * 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 libmaple/stm32f2/include/series/timer.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F2 timer support.
+ */
+
+#ifndef _LIBMAPLE_STM32F2_TIMER_H_
+#define _LIBMAPLE_STM32F2_TIMER_H_
+
+#include <libmaple/libmaple_types.h>
+#include <libmaple/gpio.h> /* for gpio_af */
+
+/*
+ * Register maps and base pointers
+ */
+
+/**
+ * @brief STM32F2 general purpose timer register map type
+ *
+ * Note that not all general purpose timers have all of these
+ * registers. Consult your chip's reference manual for the details.
+ */
+typedef struct timer_gen_reg_map {
+ __io uint32 CR1; /**< Control register 1 */
+ __io uint32 CR2; /**< Control register 2 */
+ __io uint32 SMCR; /**< Slave mode control register */
+ __io uint32 DIER; /**< DMA/Interrupt enable register */
+ __io uint32 SR; /**< Status register */
+ __io uint32 EGR; /**< Event generation register */
+ __io uint32 CCMR1; /**< Capture/compare mode register 1 */
+ __io uint32 CCMR2; /**< Capture/compare mode register 2 */
+ __io uint32 CCER; /**< Capture/compare enable register */
+ __io uint32 CNT; /**< Counter */
+ __io uint32 PSC; /**< Prescaler */
+ __io uint32 ARR; /**< Auto-reload register */
+ const uint32 RESERVED1; /**< Reserved */
+ __io uint32 CCR1; /**< Capture/compare register 1 */
+ __io uint32 CCR2; /**< Capture/compare register 2 */
+ __io uint32 CCR3; /**< Capture/compare register 3 */
+ __io uint32 CCR4; /**< Capture/compare register 4 */
+ const uint32 RESERVED2; /**< Reserved */
+ __io uint32 DCR; /**< DMA control register */
+ __io uint32 DMAR; /**< DMA address for full transfer */
+ __io uint32 OR; /**< Option register. */
+} timer_gen_reg_map;
+
+struct timer_adv_reg_map;
+struct timer_bas_reg_map;
+
+/** Timer 1 register map base pointer */
+#define TIMER1_BASE ((struct timer_adv_reg_map*)0x40010000)
+/** Timer 2 register map base pointer */
+#define TIMER2_BASE ((struct timer_gen_reg_map*)0x40000000)
+/** Timer 3 register map base pointer */
+#define TIMER3_BASE ((struct timer_gen_reg_map*)0x40000400)
+/** Timer 4 register map base pointer */
+#define TIMER4_BASE ((struct timer_gen_reg_map*)0x40000800)
+/** Timer 5 register map base pointer */
+#define TIMER5_BASE ((struct timer_gen_reg_map*)0x40000C00)
+/** Timer 6 register map base pointer */
+#define TIMER6_BASE ((struct timer_bas_reg_map*)0x40001000)
+/** Timer 7 register map base pointer */
+#define TIMER7_BASE ((struct timer_bas_reg_map*)0x40001400)
+/** Timer 8 register map base pointer */
+#define TIMER8_BASE ((struct timer_adv_reg_map*)0x40010400)
+/** Timer 9 register map base pointer */
+#define TIMER9_BASE ((struct timer_gen_reg_map*)0x40014000)
+/** Timer 10 register map base pointer */
+#define TIMER10_BASE ((struct timer_gen_reg_map*)0x40014400)
+/** Timer 11 register map base pointer */
+#define TIMER11_BASE ((struct timer_gen_reg_map*)0x40014800)
+/** Timer 12 register map base pointer */
+#define TIMER12_BASE ((struct timer_gen_reg_map*)0x40001800)
+/** Timer 13 register map base pointer */
+#define TIMER13_BASE ((struct timer_gen_reg_map*)0x40001C00)
+/** Timer 14 register map base pointer */
+#define TIMER14_BASE ((struct timer_gen_reg_map*)0x40002000)
+
+/*
+ * Register bit definitions
+ */
+
+/* TIM2 option register */
+
+/** Timer 2 option register internal trigger 1 remap */
+#define TIMER2_OR_ITR1_RMP (0x3 << 10)
+/** Timer 2 OR internal trigger 1: TIM8_TRGOUT */
+#define TIMER2_OR_ITR1_RMP_TIM8_TRGOUT (0x0 << 10)
+/** Timer 2 OR internal trigger 1: Ethernet PTP trigger output */
+#define TIMER2_OR_ITR1_RMP_PTP_TRGOUT (0x1 << 10)
+/** Timer 2 OR internal trigger 1: USB OTG full speed start of frame */
+#define TIMER2_OR_ITR1_RMP_OTG_FS_SOF (0x2 << 10)
+/** Timer 2 OR internal trigger 1: USB OTG high speed start of frame */
+#define TIMER2_OR_ITR1_RMP_OTG_HS_SOF (0x3 << 10)
+
+/* TIM5 option register */
+
+/**
+ * Timer 5 option register input 4 remap.
+ *
+ * These bits control whether TIM5_CH4 is connected to a GPIO or a
+ * clock. Connecting to a GPIO is the normal mode, useful for e.g. PWM
+ * generation or input pulse duration measurement. Connecting to a
+ * clock is useful for calibrating that clock.
+ */
+#define TIMER5_OR_TI4_RMP (0x3 << 6)
+/**
+ * Timer 5 OR input 4: Timer 5 channel 4 connected to GPIO. */
+#define TIMER5_OR_TI4_RMP_GPIO (0x0 << 6)
+/**
+ * Timer 5 OR input 4: low speed internal clock (LSI) is connected to
+ * TIM5_CH4. */
+#define TIMER5_OR_TI4_RMP_LSI (0x1 << 6)
+/**
+ * Timer 5 OR input 4: low speed external clock (LSE) is connected to
+ * TIM5_CH4. */
+#define TIMER5_OR_TI4_RMP_LSE (0x2 << 6)
+/**
+ * Timer 5 OR input 4: real time clock (RTC) output is connected to
+ * TIM5_CH4. */
+#define TIMER5_OR_TI4_RMP_RTC (0x3 << 6)
+
+/*
+ * Device pointers
+ */
+
+struct timer_dev;
+
+extern struct timer_dev *TIMER1;
+extern struct timer_dev *TIMER2;
+extern struct timer_dev *TIMER3;
+extern struct timer_dev *TIMER4;
+extern struct timer_dev *TIMER5;
+extern struct timer_dev *TIMER6;
+extern struct timer_dev *TIMER7;
+extern struct timer_dev *TIMER8;
+extern struct timer_dev *TIMER9;
+extern struct timer_dev *TIMER10;
+extern struct timer_dev *TIMER11;
+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-f4/include/series/usart.h b/libmaple/stm32f2-f4/include/series/usart.h
new file mode 100644
index 0000000..8936efa
--- /dev/null
+++ b/libmaple/stm32f2-f4/include/series/usart.h
@@ -0,0 +1,111 @@
+/******************************************************************************
+ * 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/usart.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F2 USART support.
+ */
+
+#ifndef _LIBMAPLE_STM32F2_USART_H_
+#define _LIBMAPLE_STM32F2_USART_H_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include <libmaple/gpio.h> /* for gpio_af */
+
+/*
+ * Register map base pointers.
+ */
+
+struct usart_reg_map;
+
+/** USART1 register map base pointer */
+#define USART1_BASE ((struct usart_reg_map*)0x40011000)
+/** USART2 register map base pointer */
+#define USART2_BASE ((struct usart_reg_map*)0x40004400)
+/** USART3 register map base pointer */
+#define USART3_BASE ((struct usart_reg_map*)0x40004800)
+/** UART4 register map base pointer */
+#define UART4_BASE ((struct usart_reg_map*)0x40004C00)
+/** UART5 register map base pointer */
+#define UART5_BASE ((struct usart_reg_map*)0x40005000)
+/** USART6 register map base pointer */
+#define USART6_BASE ((struct usart_reg_map*)0x40011400)
+
+/*
+ * F2-only register bit definitions.
+ */
+
+/* Control register 1 */
+
+/**
+ * @brief Oversampling mode bit.
+ * Availability: STM32F2. */
+#define USART_CR1_OVER8_BIT 15
+
+/**
+ * @brief Oversampling mode.
+ * Availability: STM32F2. */
+#define USART_CR1_OVER8 (1U << USART_CR1_OVER8_BIT)
+
+/* Control register 3 */
+
+/** One sample bit method enable bit. */
+#define USART_CR3_ONEBIT_BIT 11
+
+/** One bit sample method enable. */
+#define USART_CR3_ONEBIT (1 << USART_CR3_ONEBIT_BIT)
+/** Sample method: Three sample bit method. */
+#define USART_CR3_ONEBIT_3SAMPLE (0 << USART_CR3_ONEBIT_BIT)
+/** Sample method: One sample bit method. */
+#define USART_CR3_ONEBIT_1SAMPLE (1 << USART_CR3_ONEBIT_BIT)
+
+/*
+ * Devices
+ */
+
+struct usart_dev;
+extern struct usart_dev *USART1;
+extern struct usart_dev *USART2;
+extern struct usart_dev *USART3;
+extern struct usart_dev *UART4;
+extern struct usart_dev *UART5;
+extern struct usart_dev *USART6;
+
+/*
+ * Routines
+ */
+
+gpio_af usart_get_af(struct usart_dev *dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmaple/stm32f2-f4/isrs.S b/libmaple/stm32f2-f4/isrs.S
new file mode 100644
index 0000000..cda627a
--- /dev/null
+++ b/libmaple/stm32f2-f4/isrs.S
@@ -0,0 +1,329 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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 ISR weak declarations */
+
+ .thumb
+
+/* Default handler, as with STM32F1 */
+ .globl __default_handler
+ .type __default_handler, %function
+
+__default_handler:
+ b .
+
+ .weak __exc_nmi
+ .globl __exc_nmi
+ .set __exc_nmi, __default_handler
+ .weak __exc_hardfault
+ .globl __exc_hardfault
+ .set __exc_hardfault, __default_handler
+ .weak __exc_memmanage
+ .globl __exc_memmanage
+ .set __exc_memmanage, __default_handler
+ .weak __exc_busfault
+ .globl __exc_busfault
+ .set __exc_busfault, __default_handler
+ .weak __exc_usagefault
+ .globl __exc_usagefault
+ .set __exc_usagefault, __default_handler
+ .weak __stm32reservedexception7
+ .globl __stm32reservedexception7
+ .set __stm32reservedexception7, __default_handler
+ .weak __stm32reservedexception8
+ .globl __stm32reservedexception8
+ .set __stm32reservedexception8, __default_handler
+ .weak __stm32reservedexception9
+ .globl __stm32reservedexception9
+ .set __stm32reservedexception9, __default_handler
+ .weak __stm32reservedexception10
+ .globl __stm32reservedexception10
+ .set __stm32reservedexception10, __default_handler
+ .weak __exc_svc
+ .globl __exc_svc
+ .set __exc_svc, __default_handler
+ .weak __exc_debug_monitor
+ .globl __exc_debug_monitor
+ .set __exc_debug_monitor, __default_handler
+ .weak __stm32reservedexception13
+ .globl __stm32reservedexception13
+ .set __stm32reservedexception13, __default_handler
+ .weak __exc_pendsv
+ .globl __exc_pendsv
+ .set __exc_pendsv, __default_handler
+ .weak __exc_systick
+ .globl __exc_systick
+ .set __exc_systick, __default_handler
+ .weak __irq_wwdg
+ .globl __irq_wwdg
+ .set __irq_wwdg, __default_handler
+ .weak __irq_pvd
+ .globl __irq_pvd
+ .set __irq_pvd, __default_handler
+ .weak __irq_tamp_stamp
+ .globl __irq_tamp_stamp
+ .set __irq_tamp_stamp, __default_handler
+ .weak __irq_rtc_wkup
+ .globl __irq_rtc_wkup
+ .set __irq_rtc_wkup, __default_handler
+ .weak __irq_flash
+ .globl __irq_flash
+ .set __irq_flash, __default_handler
+ .weak __irq_rcc
+ .globl __irq_rcc
+ .set __irq_rcc, __default_handler
+ .weak __irq_exti0
+ .globl __irq_exti0
+ .set __irq_exti0, __default_handler
+ .weak __irq_exti1
+ .globl __irq_exti1
+ .set __irq_exti1, __default_handler
+ .weak __irq_exti2
+ .globl __irq_exti2
+ .set __irq_exti2, __default_handler
+ .weak __irq_exti3
+ .globl __irq_exti3
+ .set __irq_exti3, __default_handler
+ .weak __irq_exti4
+ .globl __irq_exti4
+ .set __irq_exti4, __default_handler
+ .weak __irq_dma1_stream0
+ .globl __irq_dma1_stream0
+ .set __irq_dma1_stream0, __default_handler
+ .weak __irq_dma1_stream1
+ .globl __irq_dma1_stream1
+ .set __irq_dma1_stream1, __default_handler
+ .weak __irq_dma1_stream2
+ .globl __irq_dma1_stream2
+ .set __irq_dma1_stream2, __default_handler
+ .weak __irq_dma1_stream3
+ .globl __irq_dma1_stream3
+ .set __irq_dma1_stream3, __default_handler
+ .weak __irq_dma1_stream4
+ .globl __irq_dma1_stream4
+ .set __irq_dma1_stream4, __default_handler
+ .weak __irq_dma1_stream5
+ .globl __irq_dma1_stream5
+ .set __irq_dma1_stream5, __default_handler
+ .weak __irq_dma1_stream6
+ .globl __irq_dma1_stream6
+ .set __irq_dma1_stream6, __default_handler
+ .weak __irq_adc
+ .globl __irq_adc
+ .set __irq_adc, __default_handler
+ .weak __irq_can1_tx
+ .globl __irq_can1_tx
+ .set __irq_can1_tx, __default_handler
+ .weak __irq_can1_rx0
+ .globl __irq_can1_rx0
+ .set __irq_can1_rx0, __default_handler
+ .weak __irq_can1_rx1
+ .globl __irq_can1_rx1
+ .set __irq_can1_rx1, __default_handler
+ .weak __irq_can1_sce
+ .globl __irq_can1_sce
+ .set __irq_can1_sce, __default_handler
+ .weak __irq_exti9_5
+ .globl __irq_exti9_5
+ .set __irq_exti9_5, __default_handler
+ .weak __irq_tim1_brk_tim9
+ .globl __irq_tim1_brk_tim9
+ .set __irq_tim1_brk_tim9, __default_handler
+ .weak __irq_tim1_up_tim10
+ .globl __irq_tim1_up_tim10
+ .set __irq_tim1_up_tim10, __default_handler
+ .weak __irq_tim1_trg_com_tim11
+ .globl __irq_tim1_trg_com_tim11
+ .set __irq_tim1_trg_com_tim11, __default_handler
+ .weak __irq_tim1_cc
+ .globl __irq_tim1_cc
+ .set __irq_tim1_cc, __default_handler
+ .weak __irq_tim2
+ .globl __irq_tim2
+ .set __irq_tim2, __default_handler
+ .weak __irq_tim3
+ .globl __irq_tim3
+ .set __irq_tim3, __default_handler
+ .weak __irq_tim4
+ .globl __irq_tim4
+ .set __irq_tim4, __default_handler
+ .weak __irq_i2c1_ev
+ .globl __irq_i2c1_ev
+ .set __irq_i2c1_ev, __default_handler
+ .weak __irq_i2c1_er
+ .globl __irq_i2c1_er
+ .set __irq_i2c1_er, __default_handler
+ .weak __irq_i2c2_ev
+ .globl __irq_i2c2_ev
+ .set __irq_i2c2_ev, __default_handler
+ .weak __irq_i2c2_er
+ .globl __irq_i2c2_er
+ .set __irq_i2c2_er, __default_handler
+ .weak __irq_spi1
+ .globl __irq_spi1
+ .set __irq_spi1, __default_handler
+ .weak __irq_spi2
+ .globl __irq_spi2
+ .set __irq_spi2, __default_handler
+ .weak __irq_usart1
+ .globl __irq_usart1
+ .set __irq_usart1, __default_handler
+ .weak __irq_usart2
+ .globl __irq_usart2
+ .set __irq_usart2, __default_handler
+ .weak __irq_usart3
+ .globl __irq_usart3
+ .set __irq_usart3, __default_handler
+ .weak __irq_exti15_10
+ .globl __irq_exti15_10
+ .set __irq_exti15_10, __default_handler
+ .weak __irq_rtc_alarm
+ .globl __irq_rtc_alarm
+ .set __irq_rtc_alarm, __default_handler
+ .weak __irq_otg_fs_wkup
+ .globl __irq_otg_fs_wkup
+ .set __irq_otg_fs_wkup, __default_handler
+ .weak __irq_tim8_brk_tim12
+ .globl __irq_tim8_brk_tim12
+ .set __irq_tim8_brk_tim12, __default_handler
+ .weak __irq_tim8_up_tim13
+ .globl __irq_tim8_up_tim13
+ .set __irq_tim8_up_tim13, __default_handler
+ .weak __irq_tim8_trg_com_tim14
+ .globl __irq_tim8_trg_com_tim14
+ .set __irq_tim8_trg_com_tim14, __default_handler
+ .weak __irq_tim8_cc
+ .globl __irq_tim8_cc
+ .set __irq_tim8_cc, __default_handler
+ .weak __irq_dma1_stream7
+ .globl __irq_dma1_stream7
+ .set __irq_dma1_stream7, __default_handler
+ .weak __irq_fsmc
+ .globl __irq_fsmc
+ .set __irq_fsmc, __default_handler
+ .weak __irq_sdio
+ .globl __irq_sdio
+ .set __irq_sdio, __default_handler
+ .weak __irq_tim5
+ .globl __irq_tim5
+ .set __irq_tim5, __default_handler
+ .weak __irq_spi3
+ .globl __irq_spi3
+ .set __irq_spi3, __default_handler
+ .weak __irq_uart4
+ .globl __irq_uart4
+ .set __irq_uart4, __default_handler
+ .weak __irq_uart5
+ .globl __irq_uart5
+ .set __irq_uart5, __default_handler
+ .weak __irq_tim6_dac
+ .globl __irq_tim6_dac
+ .set __irq_tim6_dac, __default_handler
+ .weak __irq_tim7
+ .globl __irq_tim7
+ .set __irq_tim7, __default_handler
+ .weak __irq_dma2_stream0
+ .globl __irq_dma2_stream0
+ .set __irq_dma2_stream0, __default_handler
+ .weak __irq_dma2_stream1
+ .globl __irq_dma2_stream1
+ .set __irq_dma2_stream1, __default_handler
+ .weak __irq_dma2_stream2
+ .globl __irq_dma2_stream2
+ .set __irq_dma2_stream2, __default_handler
+ .weak __irq_dma2_stream3
+ .globl __irq_dma2_stream3
+ .set __irq_dma2_stream3, __default_handler
+ .weak __irq_dma2_stream4
+ .globl __irq_dma2_stream4
+ .set __irq_dma2_stream4, __default_handler
+ .weak __irq_eth
+ .globl __irq_eth
+ .set __irq_eth, __default_handler
+ .weak __irq_eth_wkup
+ .globl __irq_eth_wkup
+ .set __irq_eth_wkup, __default_handler
+ .weak __irq_can2_tx
+ .globl __irq_can2_tx
+ .set __irq_can2_tx, __default_handler
+ .weak __irq_can2_rx0
+ .globl __irq_can2_rx0
+ .set __irq_can2_rx0, __default_handler
+ .weak __irq_can2_rx1
+ .globl __irq_can2_rx1
+ .set __irq_can2_rx1, __default_handler
+ .weak __irq_can2_sce
+ .globl __irq_can2_sce
+ .set __irq_can2_sce, __default_handler
+ .weak __irq_otg_fs
+ .globl __irq_otg_fs
+ .set __irq_otg_fs, __default_handler
+ .weak __irq_dma2_stream5
+ .globl __irq_dma2_stream5
+ .set __irq_dma2_stream5, __default_handler
+ .weak __irq_dma2_stream6
+ .globl __irq_dma2_stream6
+ .set __irq_dma2_stream6, __default_handler
+ .weak __irq_dma2_stream7
+ .globl __irq_dma2_stream7
+ .set __irq_dma2_stream7, __default_handler
+ .weak __irq_usart6
+ .globl __irq_usart6
+ .set __irq_usart6, __default_handler
+ .weak __irq_i2c3_ev
+ .globl __irq_i2c3_ev
+ .set __irq_i2c3_ev, __default_handler
+ .weak __irq_i2c3_er
+ .globl __irq_i2c3_er
+ .set __irq_i2c3_er, __default_handler
+ .weak __irq_otg_hs_ep1_out
+ .globl __irq_otg_hs_ep1_out
+ .set __irq_otg_hs_ep1_out, __default_handler
+ .weak __irq_otg_hs_ep1_in
+ .globl __irq_otg_hs_ep1_in
+ .set __irq_otg_hs_ep1_in, __default_handler
+ .weak __irq_otg_hs_wkup
+ .globl __irq_otg_hs_wkup
+ .set __irq_otg_hs_wkup, __default_handler
+ .weak __irq_otg_hs
+ .globl __irq_otg_hs
+ .set __irq_otg_hs, __default_handler
+ .weak __irq_dcmi
+ .globl __irq_dcmi
+ .set __irq_dcmi, __default_handler
+ .weak __irq_cryp
+ .globl __irq_cryp
+ .set __irq_cryp, __default_handler
+ .weak __irq_hash_rng
+ .globl __irq_hash_rng
+ .set __irq_hash_rng, __default_handler
+/* STM32F4 Specific */
+ .weak __irq_fpu
+ .globl __irq_fpu
+ .set __irq_fpu, __default_handler
+ .weak __irq_spi4
+ .globl __irq_spi4
+ .set __irq_spi4, __default_handler
diff --git a/libmaple/stm32f2-f4/rcc.c b/libmaple/stm32f2-f4/rcc.c
new file mode 100644
index 0000000..7fc7eb0
--- /dev/null
+++ b/libmaple/stm32f2-f4/rcc.c
@@ -0,0 +1,175 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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/rcc.c
+ * @brief STM32F2 RCC.
+ */
+
+#include <libmaple/rcc.h>
+#include <libmaple/libmaple.h>
+
+#include "rcc_private.h"
+
+#define DEV_ENTRY(domain, dev) \
+ {.clk_domain = RCC_##domain, .line_num = RCC_##domain##ENR_##dev##EN_BIT}
+
+const struct rcc_dev_info rcc_dev_table[] = {
+ /* AHB1 */
+ [RCC_OTGHSULPI] = DEV_ENTRY(AHB1, OTGHSULPI),
+ [RCC_OTGHS] = DEV_ENTRY(AHB1, OTGHS),
+ [RCC_ETHMACPTP] = DEV_ENTRY(AHB1, ETHMACPTP),
+ [RCC_ETHMACRX] = DEV_ENTRY(AHB1, ETHMACRX),
+ [RCC_ETHMACTX] = DEV_ENTRY(AHB1, ETHMACTX),
+ [RCC_ETHMAC] = DEV_ENTRY(AHB1, ETHMAC),
+ [RCC_DMA2] = DEV_ENTRY(AHB1, DMA2),
+ [RCC_DMA1] = DEV_ENTRY(AHB1, DMA1),
+ [RCC_BKPSRAM] = DEV_ENTRY(AHB1, BKPSRAM),
+ [RCC_CRC] = DEV_ENTRY(AHB1, CRC),
+ [RCC_GPIOI] = DEV_ENTRY(AHB1, GPIOI),
+ [RCC_GPIOH] = DEV_ENTRY(AHB1, GPIOH),
+ [RCC_GPIOG] = DEV_ENTRY(AHB1, GPIOG),
+ [RCC_GPIOF] = DEV_ENTRY(AHB1, GPIOF),
+ [RCC_GPIOE] = DEV_ENTRY(AHB1, GPIOE),
+ [RCC_GPIOD] = DEV_ENTRY(AHB1, GPIOD),
+ [RCC_GPIOC] = DEV_ENTRY(AHB1, GPIOC),
+ [RCC_GPIOB] = DEV_ENTRY(AHB1, GPIOB),
+ [RCC_GPIOA] = DEV_ENTRY(AHB1, GPIOA),
+
+ /* AHB2 */
+ [RCC_OTGFS] = DEV_ENTRY(AHB2, OTGFS),
+ [RCC_RNG] = DEV_ENTRY(AHB2, RNG),
+ [RCC_HASH] = DEV_ENTRY(AHB2, HASH),
+ [RCC_CRYP] = DEV_ENTRY(AHB2, CRYP),
+ [RCC_DCMI] = DEV_ENTRY(AHB2, DCMI),
+
+ /* AHB3 */
+ [RCC_FSMC] = DEV_ENTRY(AHB3, FSMC),
+
+ /* APB1 */
+ [RCC_DAC] = DEV_ENTRY(APB1, DAC),
+ [RCC_PWR] = DEV_ENTRY(APB1, PWR),
+ [RCC_CAN2] = DEV_ENTRY(APB1, CAN2),
+ [RCC_CAN1] = DEV_ENTRY(APB1, CAN1),
+ [RCC_I2C3] = DEV_ENTRY(APB1, I2C3),
+ [RCC_I2C2] = DEV_ENTRY(APB1, I2C2),
+ [RCC_I2C1] = DEV_ENTRY(APB1, I2C1),
+ [RCC_UART5] = DEV_ENTRY(APB1, UART5),
+ [RCC_UART4] = DEV_ENTRY(APB1, UART4),
+ [RCC_USART3] = DEV_ENTRY(APB1, USART3),
+ [RCC_USART2] = DEV_ENTRY(APB1, USART2),
+ [RCC_SPI3] = DEV_ENTRY(APB1, SPI3),
+ [RCC_SPI2] = DEV_ENTRY(APB1, SPI2),
+ [RCC_WWDG] = DEV_ENTRY(APB1, WWDG),
+ [RCC_TIMER14] = DEV_ENTRY(APB1, TIM14),
+ [RCC_TIMER13] = DEV_ENTRY(APB1, TIM13),
+ [RCC_TIMER12] = DEV_ENTRY(APB1, TIM12),
+ [RCC_TIMER7] = DEV_ENTRY(APB1, TIM7),
+ [RCC_TIMER6] = DEV_ENTRY(APB1, TIM6),
+ [RCC_TIMER5] = DEV_ENTRY(APB1, TIM5),
+ [RCC_TIMER4] = DEV_ENTRY(APB1, TIM4),
+ [RCC_TIMER3] = DEV_ENTRY(APB1, TIM3),
+ [RCC_TIMER2] = DEV_ENTRY(APB1, TIM2),
+
+ /* APB2 */
+ [RCC_TIMER11] = DEV_ENTRY(APB2, TIM11),
+ [RCC_TIMER10] = DEV_ENTRY(APB2, TIM10),
+ [RCC_TIMER9] = DEV_ENTRY(APB2, TIM9),
+ [RCC_SYSCFG] = DEV_ENTRY(APB2, SYSCFG),
+ [RCC_SPI1] = DEV_ENTRY(APB2, SPI1),
+ [RCC_SDIO] = DEV_ENTRY(APB2, SDIO),
+ [RCC_ADC3] = DEV_ENTRY(APB2, ADC3),
+ [RCC_ADC2] = DEV_ENTRY(APB2, ADC2),
+ [RCC_ADC1] = DEV_ENTRY(APB2, ADC1),
+ [RCC_USART6] = DEV_ENTRY(APB2, USART6),
+ [RCC_USART1] = DEV_ENTRY(APB2, USART1),
+ [RCC_TIMER8] = DEV_ENTRY(APB2, TIM8),
+ [RCC_TIMER1] = DEV_ENTRY(APB2, TIM1),
+};
+
+void rcc_clk_enable(rcc_clk_id id) {
+ static __io uint32* enable_regs[] = {
+ [RCC_AHB1] = &RCC_BASE->AHB1ENR,
+ [RCC_AHB2] = &RCC_BASE->AHB2ENR,
+ [RCC_AHB3] = &RCC_BASE->AHB3ENR,
+ [RCC_APB1] = &RCC_BASE->APB1ENR,
+ [RCC_APB2] = &RCC_BASE->APB2ENR,
+ };
+ rcc_do_clk_enable(enable_regs, id);
+}
+
+void rcc_reset_dev(rcc_clk_id id) {
+ static __io uint32* reset_regs[] = {
+ [RCC_AHB1] = &RCC_BASE->AHB1RSTR,
+ [RCC_AHB2] = &RCC_BASE->AHB2RSTR,
+ [RCC_AHB3] = &RCC_BASE->AHB3RSTR,
+ [RCC_APB1] = &RCC_BASE->AHB3RSTR,
+ [RCC_APB2] = &RCC_BASE->AHB3RSTR,
+ };
+ rcc_do_reset_dev(reset_regs, id);
+}
+
+void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider) {
+ static const uint32 masks[] = {
+ [RCC_PRESCALER_MCO2] = RCC_CFGR_MCO2PRE,
+ [RCC_PRESCALER_MCO1] = RCC_CFGR_MCO1PRE,
+ [RCC_PRESCALER_RTC] = RCC_CFGR_RTCPRE,
+ [RCC_PRESCALER_APB2] = RCC_CFGR_PPRE2,
+ [RCC_PRESCALER_APB1] = RCC_CFGR_PPRE1,
+ [RCC_PRESCALER_AHB] = RCC_CFGR_HPRE,
+ };
+ rcc_do_set_prescaler(masks, prescaler, divider);
+}
+
+/* pll_cfg->data must point to a struct stm32f2_rcc_pll_data. */
+void rcc_configure_pll(rcc_pll_cfg *pll_cfg) {
+ stm32f2_rcc_pll_data *data = pll_cfg->data;
+ uint32 pllcfgr;
+
+ /* Check that the PLL is disabled. */
+ ASSERT_FAULT(!rcc_is_clk_on(RCC_CLK_PLL));
+
+ /* Sanity-check all the parameters */
+ ASSERT_FAULT((data->pllq >= 4) && (data->pllq <= 15));
+ ASSERT_FAULT((data->pllp >= 2) && (data->pllp <= 8));
+ ASSERT_FAULT(!(data->pllp & 1));
+ ASSERT_FAULT((data->plln >= 192) && (data->plln <= 432));
+ ASSERT_FAULT((data->pllm >= 2) && (data->pllm <= 63));
+
+ /* Update RCC_PLLCFGR to reflect new values. */
+ pllcfgr = RCC_BASE->PLLCFGR;
+ pllcfgr &= ~(RCC_PLLCFGR_PLLQ |
+ RCC_PLLCFGR_PLLP |
+ RCC_PLLCFGR_PLLN |
+ RCC_PLLCFGR_PLLM |
+ RCC_PLLCFGR_PLLSRC);
+ pllcfgr |= (pll_cfg->pllsrc |
+ (data->pllq << 24) |
+ (((data->pllp >> 1) - 1) << 16) |
+ (data->plln << 6) |
+ data->pllm);
+ RCC_BASE->PLLCFGR = pllcfgr;
+}
diff --git a/libmaple/stm32f2-f4/rules.mk b/libmaple/stm32f2-f4/rules.mk
new file mode 100644
index 0000000..4c62cc2
--- /dev/null
+++ b/libmaple/stm32f2-f4/rules.mk
@@ -0,0 +1,40 @@
+# Standard things
+sp := $(sp).x
+dirstack_$(sp) := $(d)
+d := $(dir)
+BUILDDIRS += $(BUILD_PATH)/$(d)
+
+# Local flags
+CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) $(LIBMAPLE_PRIVATE_INCLUDES) -Wall -Werror
+
+# Local rules and targets
+sSRCS_$(d) := isrs.S
+sSRCS_$(d) += vector_table.S
+
+cSRCS_$(d) := adc.c
+cSRCS_$(d) += dma.c
+cSRCS_$(d) += exti.c
+cSRCS_$(d) += fsmc.c
+cSRCS_$(d) += gpio.c
+cSRCS_$(d) += rcc.c
+cSRCS_$(d) += spi.c
+cSRCS_$(d) += syscfg.c
+cSRCS_$(d) += timer.c
+cSRCS_$(d) += usart.c
+
+sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%)
+cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%)
+
+OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \
+ $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o)
+DEPS_$(d) := $(OBJS_$(d):%.o=%.d)
+
+$(OBJS_$(d)): TGT_ASFLAGS :=
+$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d))
+
+TGT_BIN += $(OBJS_$(d))
+
+# Standard things
+-include $(DEPS_$(d))
+d := $(dirstack_$(sp))
+sp := $(basename $(sp))
diff --git a/libmaple/stm32f2-f4/spi.c b/libmaple/stm32f2-f4/spi.c
new file mode 100644
index 0000000..cfd9995
--- /dev/null
+++ b/libmaple/stm32f2-f4/spi.c
@@ -0,0 +1,88 @@
+/******************************************************************************
+ * 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/spi.c
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F2 SPI/I2S.
+ */
+
+#include <libmaple/spi.h>
+#include "spi_private.h"
+
+/*
+ * Devices
+ */
+
+static spi_dev spi1 = SPI_DEV(1);
+static spi_dev spi2 = SPI_DEV(2);
+static spi_dev spi3 = SPI_DEV(3);
+
+spi_dev *SPI1 = &spi1;
+spi_dev *SPI2 = &spi2;
+spi_dev *SPI3 = &spi3;
+
+/*
+ * Routines
+ */
+
+void spi_config_gpios(spi_dev *dev,
+ uint8 as_master,
+ gpio_dev *nss_dev,
+ uint8 nss_bit,
+ gpio_dev *comm_dev,
+ uint8 sck_bit,
+ uint8 miso_bit,
+ uint8 mosi_bit) {
+ gpio_af dev_af = spi_get_af(dev);
+ gpio_set_mode(nss_dev, nss_bit, GPIO_MODE_AF);
+ gpio_set_mode(comm_dev, sck_bit, GPIO_MODE_AF);
+ gpio_set_mode(comm_dev, miso_bit, GPIO_MODE_AF);
+ gpio_set_mode(comm_dev, mosi_bit, GPIO_MODE_AF);
+ gpio_set_af(nss_dev, nss_bit, dev_af);
+ gpio_set_af(comm_dev, sck_bit, dev_af);
+ gpio_set_af(comm_dev, miso_bit, dev_af);
+ gpio_set_af(comm_dev, mosi_bit, dev_af);
+}
+
+void spi_foreach(void (*fn)(spi_dev*)) {
+ fn(SPI1);
+ fn(SPI2);
+ fn(SPI3);
+}
+
+gpio_af spi_get_af(spi_dev *dev) {
+ switch (dev->clk_id) {
+ case RCC_SPI1: /* Fall through */
+ case RCC_SPI2:
+ return GPIO_AF_SPI_1_2;
+ case RCC_SPI3:
+ return GPIO_AF_SPI3;
+ default:
+ ASSERT(0); /* Can't happen */
+ return (gpio_af)-1;
+ }
+}
diff --git a/libmaple/stm32f2-f4/syscfg.c b/libmaple/stm32f2-f4/syscfg.c
new file mode 100644
index 0000000..19e932e
--- /dev/null
+++ b/libmaple/stm32f2-f4/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 <libmaple/syscfg.h>
+#include <libmaple/bitband.h>
+#include <libmaple/rcc.h>
+
+/**
+ * @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/libmaple/stm32f2-f4/timer.c b/libmaple/stm32f2-f4/timer.c
new file mode 100644
index 0000000..4ef466a
--- /dev/null
+++ b/libmaple/stm32f2-f4/timer.c
@@ -0,0 +1,171 @@
+/******************************************************************************
+ * 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/timer.c
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F2 timers.
+ */
+
+#include <libmaple/timer.h>
+#include <libmaple/stm32.h>
+#include "timer_private.h"
+
+/*
+ * Routines
+ */
+
+/**
+ * @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.
+ *
+ * @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
+ *
+ * Defer to the timer_private dispatch API.
+ */
+
+void __irq_tim1_brk_tim9(void) {
+ dispatch_adv_brk(TIMER1);
+#if STM32_HAVE_TIMER(9)
+ dispatch_tim_9_12(TIMER9);
+#endif
+}
+
+void __irq_tim1_up_tim10(void) {
+ dispatch_adv_up(TIMER1);
+#if STM32_HAVE_TIMER(10)
+ dispatch_tim_10_11_13_14(TIMER10);
+#endif
+}
+
+void __irq_tim1_trg_com_tim11(void) {
+ dispatch_adv_trg_com(TIMER1);
+#if STM32_HAVE_TIMER(11)
+ dispatch_tim_10_11_13_14(TIMER11);
+#endif
+}
+
+void __irq_tim1_cc(void) {
+ dispatch_adv_cc(TIMER1);
+}
+
+void __irq_tim2(void) {
+ dispatch_general(TIMER2);
+}
+
+void __irq_tim3(void) {
+ dispatch_general(TIMER3);
+}
+
+void __irq_tim4(void) {
+ dispatch_general(TIMER4);
+}
+
+void __irq_tim5(void) {
+ dispatch_general(TIMER5);
+}
+
+/* FIXME: this is also the DAC DMA underrun interrupt, so it needs a
+ * different name (and to be supported?). */
+void __irq_tim6(void) {
+ dispatch_basic(TIMER6);
+}
+
+void __irq_tim7(void) {
+#if STM32_HAVE_TIMER(7)
+ dispatch_basic(TIMER7);
+#endif
+}
+
+void __irq_tim8_brk_tim12(void) {
+#if STM32_HAVE_TIMER(8)
+ dispatch_adv_brk(TIMER8);
+#endif
+#if STM32_HAVE_TIMER(12)
+ dispatch_tim_9_12(TIMER12);
+#endif
+}
+
+void __irq_tim8_up_tim13(void) {
+#if STM32_HAVE_TIMER(8)
+ dispatch_adv_up(TIMER8);
+#endif
+#if STM32_HAVE_TIMER(13)
+ dispatch_tim_10_11_13_14(TIMER13);
+#endif
+}
+
+void __irq_tim8_trg_com_tim14(void) {
+#if STM32_HAVE_TIMER(8)
+ dispatch_adv_trg_com(TIMER8);
+#endif
+#if STM32_HAVE_TIMER(14)
+ dispatch_tim_10_11_13_14(TIMER14);
+#endif
+}
+
+void __irq_tim8_cc(void) {
+#if STM32_HAVE_TIMER(8)
+ dispatch_adv_cc(TIMER8);
+#endif
+}
diff --git a/libmaple/stm32f2-f4/usart.c b/libmaple/stm32f2-f4/usart.c
new file mode 100644
index 0000000..fce122f
--- /dev/null
+++ b/libmaple/stm32f2-f4/usart.c
@@ -0,0 +1,204 @@
+/******************************************************************************
+ * 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/usart.c
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F2 USART.
+ */
+
+#include <libmaple/usart.h>
+#include <libmaple/gpio.h>
+#include "usart_private.h"
+
+/*
+ * Devices
+ */
+
+static ring_buffer usart1_rb;
+static usart_dev usart1 = {
+ .regs = USART1_BASE,
+ .rb = &usart1_rb,
+ .max_baud = 4500000UL, /* TODO: are these correct? 5250000UL for STM32F4? */
+ .clk_id = RCC_USART1,
+ .irq_num = NVIC_USART1,
+};
+/** USART1 device */
+usart_dev *USART1 = &usart1;
+
+static ring_buffer usart2_rb;
+static usart_dev usart2 = {
+ .regs = USART2_BASE,
+ .rb = &usart2_rb,
+ .max_baud = 2250000UL, /* TODO: are these correct? 2620000UL for STM32F4? */
+ .clk_id = RCC_USART2,
+ .irq_num = NVIC_USART2,
+};
+/** USART2 device */
+usart_dev *USART2 = &usart2;
+
+static ring_buffer usart3_rb;
+static usart_dev usart3 = {
+ .regs = USART3_BASE,
+ .rb = &usart3_rb,
+ .max_baud = 2250000UL, /* TODO: are these correct? */
+ .clk_id = RCC_USART3,
+ .irq_num = NVIC_USART3,
+};
+/** USART3 device */
+usart_dev *USART3 = &usart3;
+
+static ring_buffer uart4_rb;
+static usart_dev uart4 = {
+ .regs = UART4_BASE,
+ .rb = &uart4_rb,
+ .max_baud = 2250000UL, /* TODO: are these correct? */
+ .clk_id = RCC_UART4,
+ .irq_num = NVIC_UART4,
+};
+/** UART4 device */
+usart_dev *UART4 = &uart4;
+
+static ring_buffer uart5_rb;
+static usart_dev uart5 = {
+ .regs = UART5_BASE,
+ .rb = &uart5_rb,
+ .max_baud = 2250000UL, /* TODO: are these correct? */
+ .clk_id = RCC_UART5,
+ .irq_num = NVIC_UART5,
+};
+/** UART5 device */
+usart_dev *UART5 = &uart5;
+
+static ring_buffer usart6_rb;
+static usart_dev usart6 = {
+ .regs = USART6_BASE,
+ .rb = &usart6_rb,
+ .max_baud = 4500000UL, /* TODO: are these correct? 5250000UL for STM32F4? */
+ .clk_id = RCC_USART6,
+ .irq_num = NVIC_USART6,
+};
+usart_dev *USART6 = &usart6;
+
+/*
+ * Routines
+ */
+
+void usart_config_gpios_async(usart_dev *udev,
+ gpio_dev *rx_dev, uint8 rx,
+ gpio_dev *tx_dev, uint8 tx,
+ unsigned flags) {
+ gpio_af af = usart_get_af(udev);
+ gpio_set_modef(rx_dev, rx, GPIO_MODE_AF, 0);
+ gpio_set_modef(tx_dev, tx, GPIO_MODE_AF, 0);
+ gpio_set_af(rx_dev, rx, af);
+ gpio_set_af(tx_dev, tx, af);
+}
+
+void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud) {
+ uint32 integer_part;
+ uint32 fractional_part;
+ uint32 tmp;
+ uint32 over8 = !!(dev->regs->CR1 & USART_CR1_OVER8);
+
+ ASSERT(!over8); /* OVER8 is currently unsupported. */
+
+ /* Figure out the clock speed, if the user doesn't give one. */
+ if (clock_speed == 0) {
+ clock_speed = _usart_clock_freq(dev);
+ }
+ ASSERT(clock_speed);
+
+ /* Convert desired baud rate to baud rate register setting. */
+ integer_part = (25 * clock_speed) / (2 * (2 - over8) * baud);
+ tmp = (integer_part / 100) << 4;
+ fractional_part = integer_part - (100 * (tmp >> 4));
+ tmp |= ((fractional_part * 16 + 50) / 100) & (uint8)0x0F;
+
+ dev->regs->BRR = tmp;
+}
+
+/**
+ * @brief Call a function on each USART.
+ * @param fn Function to call.
+ */
+void usart_foreach(void (*fn)(usart_dev*)) {
+ fn(USART1);
+ fn(USART2);
+ fn(USART3);
+ fn(UART4);
+ fn(UART5);
+ fn(USART6);
+}
+
+/**
+ * @brief Get GPIO alternate function mode for a USART.
+ * @param dev USART whose gpio_af to get.
+ * @return gpio_af corresponding to dev.
+ */
+gpio_af usart_get_af(usart_dev *dev) {
+ switch (dev->clk_id) {
+ case RCC_USART1:
+ case RCC_USART2:
+ case RCC_USART3:
+ return GPIO_AF_USART_1_2_3;
+ case RCC_UART4:
+ case RCC_UART5:
+ case RCC_USART6:
+ return GPIO_AF_USART_4_5_6;
+ default:
+ ASSERT(0); /* Can't happen */
+ return (gpio_af)-1;
+ }
+}
+
+/*
+ * Interrupt handlers.
+ */
+
+void __irq_usart1(void) {
+ usart_irq(&usart1_rb, USART1_BASE);
+}
+
+void __irq_usart2(void) {
+ usart_irq(&usart2_rb, USART2_BASE);
+}
+
+void __irq_usart3(void) {
+ usart_irq(&usart3_rb, USART3_BASE);
+}
+
+void __irq_uart4(void) {
+ usart_irq(&uart4_rb, UART4_BASE);
+}
+
+void __irq_uart5(void) {
+ usart_irq(&uart5_rb, UART5_BASE);
+}
+
+void __irq_usart6(void) {
+ usart_irq(&usart6_rb, USART6_BASE);
+}
diff --git a/libmaple/stm32f2-f4/vector_table.S b/libmaple/stm32f2-f4/vector_table.S
new file mode 100644
index 0000000..752503b
--- /dev/null
+++ b/libmaple/stm32f2-f4/vector_table.S
@@ -0,0 +1,138 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 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 vector table */
+
+ .section ".stm32.interrupt_vector"
+
+ .globl __stm32_vector_table
+ .type __stm32_vector_table, %object
+
+__stm32_vector_table:
+/* CM3 core interrupts */
+ .long __msp_init
+ .long __exc_reset
+ .long __exc_nmi
+ .long __exc_hardfault
+ .long __exc_memmanage
+ .long __exc_busfault
+ .long __exc_usagefault
+ .long __stm32reservedexception7
+ .long __stm32reservedexception8
+ .long __stm32reservedexception9
+ .long __stm32reservedexception10
+ .long __exc_svc
+ .long __exc_debug_monitor
+ .long __stm32reservedexception13
+ .long __exc_pendsv
+ .long __exc_systick
+/* Peripheral interrupts */
+ .long __irq_wwdg
+ .long __irq_pvd
+ .long __irq_tamp_stamp
+ .long __irq_rtc_wkup
+ .long __irq_flash
+ .long __irq_rcc
+ .long __irq_exti0
+ .long __irq_exti1
+ .long __irq_exti2
+ .long __irq_exti3
+ .long __irq_exti4
+ .long __irq_dma1_stream0
+ .long __irq_dma1_stream1
+ .long __irq_dma1_stream2
+ .long __irq_dma1_stream3
+ .long __irq_dma1_stream4
+ .long __irq_dma1_stream5
+ .long __irq_dma1_stream6
+ .long __irq_adc
+ .long __irq_can1_tx
+ .long __irq_can1_rx0
+ .long __irq_can1_rx1
+ .long __irq_can1_sce
+ .long __irq_exti9_5
+ .long __irq_tim1_brk_tim9
+ .long __irq_tim1_up_tim10
+ .long __irq_tim1_trg_com_tim11
+ .long __irq_tim1_cc
+ .long __irq_tim2
+ .long __irq_tim3
+ .long __irq_tim4
+ .long __irq_i2c1_ev
+ .long __irq_i2c1_er
+ .long __irq_i2c2_ev
+ .long __irq_i2c2_er
+ .long __irq_spi1
+ .long __irq_spi2
+ .long __irq_usart1
+ .long __irq_usart2
+ .long __irq_usart3
+ .long __irq_exti15_10
+ .long __irq_rtc_alarm
+ .long __irq_otg_fs_wkup
+ .long __irq_tim8_brk_tim12
+ .long __irq_tim8_up_tim13
+ .long __irq_tim8_trg_com_tim14
+ .long __irq_tim8_cc
+ .long __irq_dma1_stream7
+ .long __irq_fsmc
+ .long __irq_sdio
+ .long __irq_tim5
+ .long __irq_spi3
+ .long __irq_uart4
+ .long __irq_uart5
+ .long __irq_tim6_dac
+ .long __irq_tim7
+ .long __irq_dma2_stream0
+ .long __irq_dma2_stream1
+ .long __irq_dma2_stream2
+ .long __irq_dma2_stream3
+ .long __irq_dma2_stream4
+ .long __irq_eth
+ .long __irq_eth_wkup
+ .long __irq_can2_tx
+ .long __irq_can2_rx0
+ .long __irq_can2_rx1
+ .long __irq_can2_sce
+ .long __irq_otg_fs
+ .long __irq_dma2_stream5
+ .long __irq_dma2_stream6
+ .long __irq_dma2_stream7
+ .long __irq_usart6
+ .long __irq_i2c3_ev
+ .long __irq_i2c3_er
+ .long __irq_otg_hs_ep1_out
+ .long __irq_otg_hs_ep1_in
+ .long __irq_otg_hs_wkup
+ .long __irq_otg_hs
+ .long __irq_dcmi
+ .long __irq_cryp
+ .long __irq_hash_rng
+/* STM32F4-specific */
+ .long __irq_fpu
+ .long __irq_spi4
+
+ .size __stm32_vector_table, . - __stm32_vector_table