aboutsummaryrefslogtreecommitdiffstats
path: root/docs/source/libmaple
diff options
context:
space:
mode:
Diffstat (limited to 'docs/source/libmaple')
-rw-r--r--docs/source/libmaple/api/adc.rst231
-rw-r--r--docs/source/libmaple/api/bitband.rst15
-rw-r--r--docs/source/libmaple/api/bkp.rst79
-rw-r--r--docs/source/libmaple/api/dac.rst123
-rw-r--r--docs/source/libmaple/api/delay.rst11
-rw-r--r--docs/source/libmaple/api/dma.rst215
-rw-r--r--docs/source/libmaple/api/exti.rst37
-rw-r--r--docs/source/libmaple/api/flash.rst249
-rw-r--r--docs/source/libmaple/api/fsmc.rst235
-rw-r--r--docs/source/libmaple/api/gpio.rst243
-rw-r--r--docs/source/libmaple/api/i2c.rst124
-rw-r--r--docs/source/libmaple/api/iwdg.rst80
-rw-r--r--docs/source/libmaple/api/libmaple.rst11
-rw-r--r--docs/source/libmaple/api/libmaple_types.rst85
-rw-r--r--docs/source/libmaple/api/nvic.rst67
-rw-r--r--docs/source/libmaple/api/pwr.rst51
-rw-r--r--docs/source/libmaple/api/rcc-reg-bits.txt1017
-rw-r--r--docs/source/libmaple/api/rcc.rst360
-rw-r--r--docs/source/libmaple/api/ring_buffer.rst27
-rw-r--r--docs/source/libmaple/api/scb.rst156
-rw-r--r--docs/source/libmaple/api/spi.rst187
-rw-r--r--docs/source/libmaple/api/stm32.rst121
-rw-r--r--docs/source/libmaple/api/systick.rst62
-rw-r--r--docs/source/libmaple/api/timer.rst453
-rw-r--r--docs/source/libmaple/api/usart.rst197
-rw-r--r--docs/source/libmaple/api/util.rst54
-rw-r--r--docs/source/libmaple/apis.rst14
-rw-r--r--docs/source/libmaple/coding-standard.rst422
-rw-r--r--docs/source/libmaple/contributing.rst176
-rw-r--r--docs/source/libmaple/overview.rst516
30 files changed, 5618 insertions, 0 deletions
diff --git a/docs/source/libmaple/api/adc.rst b/docs/source/libmaple/api/adc.rst
new file mode 100644
index 0000000..2f06926
--- /dev/null
+++ b/docs/source/libmaple/api/adc.rst
@@ -0,0 +1,231 @@
+.. highlight:: c
+.. _libmaple-adc:
+
+``<libmaple/adc.h>``
+====================
+
+:ref:`Analog to Digital Conversion <adc>` (ADC) support.
+
+A common API for basic ADC functionality is available, but the
+characteristics of the ADC peripherals vary slightly across
+targets. To manage this, each target defines a small set of datatypes
+expressing its capabilities (namely :ref:`adc_extsel_event
+<adc-adc_extsel_event>`, :ref:`adc_smp_rate <adc-adc_smp_rate>`, and
+:ref:`adc_prescaler <adc-adc_prescaler>`).
+
+.. contents:: Contents
+ :local:
+ :depth: 2
+
+Devices
+-------
+
+The individual ADC peripherals have the following device struct.
+
+.. doxygenstruct:: adc_dev
+
+The available ADC peripherals vary by target. The complete list is
+``ADC1``, ``ADC2``, and ``ADC3``.
+
+.. doxygenvariable:: ADC1
+.. doxygenvariable:: ADC2
+.. doxygenvariable:: ADC3
+
+Functions
+---------
+
+Activation and Deactivation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``adc_enable_single_swstart()`` is simple, portable function, which
+enables an ADC and sets it up for its basic usage: performing single
+conversions using :ref:`adc_read() <adc-adc_read>`.
+
+.. _adc-adc_enable_single_swstart:
+.. doxygenfunction:: adc_enable_single_swstart
+
+The precise software sequence used varies by target, so this is a good
+function to use if your program needs to support multiple MCUs. By
+default, Wirish calls ``adc_enable_single_swstart()`` on all available
+ADCs at ``init()`` time, so Wirish users don't have to call this
+function.
+
+There are several other lower-level routines used for activating and
+deactivating ADCs:
+
+.. _adc-adc_init:
+.. doxygenfunction:: adc_init
+.. _adc-adc_enable:
+.. doxygenfunction:: adc_enable
+.. _adc-adc_disable:
+.. doxygenfunction:: adc_disable
+.. _adc-adc_disable_all:
+.. doxygenfunction:: adc_disable_all
+
+ADC Conversion
+~~~~~~~~~~~~~~
+
+``adc_read()`` is a simple function which starts conversion on a
+single ADC channel, blocks until it has completed, and returns the
+converted result. Don't use the ADC device for any other purpose while
+it's running.
+
+.. _adc-adc_read:
+.. doxygenfunction:: adc_read
+
+To use ``adc_read()``, the device must be configured appropriately.
+You can do this with :ref:`adc_enable_single_swstart()
+<adc-adc_enable_single_swstart>`.
+
+Note that for an ADC device to perform conversion on a GPIO input
+(which is the usual case; the notable exception being taking
+temperature reading), the pin must be configured for analog
+conversion. Do this with :ref:`adc_config_gpio()
+<adc-adc_config_gpio>`.
+
+Other routines helpful for ADC conversion:
+
+.. _adc-adc_set_reg_seqlen:
+.. doxygenfunction:: adc_set_reg_seqlen
+.. _adc-adc_set_extsel:
+.. doxygenfunction:: adc_set_extsel
+
+.. _adc-adc_extsel_event:
+
+The last of these, :ref:`adc_set_extsel() <adc-adc_set_extsel>`, takes
+a target-dependent ``adc_extsel_event`` argument.
+
+STM32F1 Targets
++++++++++++++++
+
+.. doxygenenum:: stm32f1::adc_extsel_event
+
+STM32F2 Targets
++++++++++++++++
+
+.. doxygenenum:: stm32f2::adc_extsel_event
+
+ADC Clock Prescaler
+~~~~~~~~~~~~~~~~~~~
+
+``adc_set_prescaler()`` is available for setting the prescaler which
+determines the common ADC clock rate. (Wirish sets a sensible default
+for this, so Wirish users ordinarily don't need to call this
+function.)
+
+.. warning:: Increasing the ADC clock rate does speed conversion time,
+ but the ADC peripherals have a maximum clock rate which must not be
+ exceeded. Make sure to configure your system and ADC clocks to
+ respect your device's maximum rate.
+
+.. _adc_adc_set_prescaler:
+.. doxygenfunction:: adc_set_prescaler
+
+.. _adc-adc_prescaler:
+
+ADC prescaler values are target-dependent.
+
+STM32F1 Targets
++++++++++++++++
+
+.. doxygenenum:: stm32f1::adc_prescaler
+
+STM32F2 Targets
++++++++++++++++
+
+.. doxygenenum:: stm32f2::adc_prescaler
+
+.. _adc-adc_set_sample_rate:
+
+ADC Sample Time
+~~~~~~~~~~~~~~~
+
+You can control the sampling time (in ADC cycles) for an entire ADC
+device using ``adc_set_sample_rate()`` [#fchansamp]_. This function
+**only controls the sample rate**; the total conversion time is equal
+to the sample time plus an additional number of ADC cycles. Consult
+the reference manual for your chip for more details.
+
+.. warning:: Decreasing ADC sample time speeds conversion, but it also
+ decreases the maximum allowable impedance of the voltage source you
+ are measuring. If your voltage source has a high impedance
+ (e.g. you're measuring Vcc through a potentiometer), and your
+ sample time is too low, you will get inaccurate results. Consult
+ the datasheet for your target for more details.
+
+.. note:: Wirish sets a sensible default sample rate to allow for
+ high-impedance inputs at ``init()`` time, but Wirish users who know
+ what they're doing may want to call this function to speed up ADC
+ conversion.
+
+.. doxygenfunction:: adc_set_sample_rate
+
+.. _adc-adc_smp_rate:
+
+The ``adc_smp_rate`` argument to :ref:`adc_set_sample_rate()
+<adc-adc_set_sample_rate>` is target-dependent.
+
+STM32F1 Targets
++++++++++++++++
+
+.. doxygenenum:: stm32f1::adc_smp_rate
+
+STM32F2 Targets
++++++++++++++++
+
+.. doxygenenum:: stm32f2::adc_smp_rate
+
+Miscellaneous
+~~~~~~~~~~~~~
+
+.. FIXME [0.0.13] why don't adc_config_gpio()'s docs show up?
+
+.. _adc-adc_foreach:
+.. doxygenfunction:: adc_foreach
+
+.. _adc-adc_config_gpio:
+.. doxygenfunction:: adc_config_gpio
+
+STM32F1 only
+~~~~~~~~~~~~
+
+The following routines are available only on STM32F1 targets.
+
+.. _adc-adc_set_exttrig:
+.. doxygenfunction:: adc_set_exttrig
+
+``adc_calibrate()`` performs calibration necessary on STM32F1 before
+using an ADC. Note that on STM32F1 targets,
+:ref:`adc_enable_single_swstart() <adc-adc_enable_single_swstart>`
+calls ``adc_calibrate()``, so there's no need to do it separately.
+
+.. _adc-adc_calibrate:
+.. doxygenfunction:: adc_calibrate
+
+Register Maps
+-------------
+
+Individual ADC peripherals have the following register map. The base
+pointers are ``ADC1_BASE``, ``ADC2_BASE``, and ``ADC3_BASE``.
+
+.. _adc-adc_reg_map:
+.. doxygenstruct:: adc_reg_map
+
+On **STM32F2 targets**, there is an additional common set of registers
+shared by all ADC peripherals. Its base pointer is
+``ADC_COMMON_BASE``.
+
+.. _adc-adc_common_reg_map:
+.. doxygenstruct:: stm32f2::adc_common_reg_map
+
+Register Bit Definitions
+------------------------
+
+.. TODO [0.0.13]
+
+TODO
+
+.. rubric:: Footnotes
+
+.. [#fchansamp] Per-channel sample time configuration is possible,
+ but currently unsupported.
diff --git a/docs/source/libmaple/api/bitband.rst b/docs/source/libmaple/api/bitband.rst
new file mode 100644
index 0000000..768f678
--- /dev/null
+++ b/docs/source/libmaple/api/bitband.rst
@@ -0,0 +1,15 @@
+.. highlight:: c
+.. _libmaple-bitband:
+
+``<libmaple/bitband.h>``
+========================
+
+Bit-banding support.
+
+Functions
+---------
+
+.. doxygenfunction:: bb_sram_get_bit
+.. doxygenfunction:: bb_sram_set_bit
+.. doxygenfunction:: bb_peri_get_bit
+.. doxygenfunction:: bb_peri_set_bit
diff --git a/docs/source/libmaple/api/bkp.rst b/docs/source/libmaple/api/bkp.rst
new file mode 100644
index 0000000..4f0115b
--- /dev/null
+++ b/docs/source/libmaple/api/bkp.rst
@@ -0,0 +1,79 @@
+.. highlight:: c
+.. _libmaple-bkp:
+
+``bkp.h``
+=========
+
+Backup register (BKP) suport.
+
+.. contents:: Contents
+ :local:
+
+Types
+-----
+
+.. doxygenstruct:: bkp_dev
+.. doxygenstruct:: bkp_reg_map
+
+Devices
+-------
+
+.. doxygenvariable:: BKP
+
+Convenience Functions
+---------------------
+
+.. doxygenfunction:: bkp_init
+.. doxygenfunction:: bkp_enable_writes
+.. doxygenfunction:: bkp_disable_writes
+.. doxygenfunction:: bkp_read
+.. doxygenfunction:: bkp_write
+
+Register Map Base Pointers
+--------------------------
+
+.. doxygendefine:: BKP_BASE
+
+Register Bit Definitions
+------------------------
+
+Data Registers
+~~~~~~~~~~~~~~
+
+.. doxygendefine:: BKP_DR_D
+
+RTC Clock Calibration Register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: BKP_RTCCR_ASOS_BIT
+.. doxygendefine:: BKP_RTCCR_ASOE_BIT
+.. doxygendefine:: BKP_RTCCR_CCO_BIT
+
+.. doxygendefine:: BKP_RTCCR_ASOS
+.. doxygendefine:: BKP_RTCCR_ASOE
+.. doxygendefine:: BKP_RTCCR_CCO
+.. doxygendefine:: BKP_RTCCR_CAL
+
+Backup control register
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: BKP_CR_TPAL_BIT
+.. doxygendefine:: BKP_CR_TPE_BIT
+
+.. doxygendefine:: BKP_CR_TPAL
+.. doxygendefine:: BKP_CR_TPE
+
+Backup control/status register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: BKP_CSR_TIF_BIT
+.. doxygendefine:: BKP_CSR_TEF_BIT
+.. doxygendefine:: BKP_CSR_TPIE_BIT
+.. doxygendefine:: BKP_CSR_CTI_BIT
+.. doxygendefine:: BKP_CSR_CTE_BIT
+
+.. doxygendefine:: BKP_CSR_TIF
+.. doxygendefine:: BKP_CSR_TEF
+.. doxygendefine:: BKP_CSR_TPIE
+.. doxygendefine:: BKP_CSR_CTI
+.. doxygendefine:: BKP_CSR_CTE
diff --git a/docs/source/libmaple/api/dac.rst b/docs/source/libmaple/api/dac.rst
new file mode 100644
index 0000000..55c8faf
--- /dev/null
+++ b/docs/source/libmaple/api/dac.rst
@@ -0,0 +1,123 @@
+.. highlight:: c
+.. _libmaple-dac:
+
+``dac.h``
+=========
+
+Digital to Analog Conversion (DAC) support.
+
+.. contents:: Contents
+ :local:
+
+Types
+-----
+
+.. doxygenstruct:: dac_dev
+.. doxygenstruct:: dac_reg_map
+
+Devices
+-------
+
+.. doxygenvariable:: DAC
+
+Functions
+---------
+
+.. doxygenfunction:: dac_init
+.. doxygenfunction:: dac_write_channel
+.. doxygenfunction:: dac_enable_channel
+.. doxygenfunction:: dac_disable_channel
+
+Register Map Base Pointers
+--------------------------
+
+.. doxygendefine:: DAC_BASE
+
+Register Bit Definitions
+------------------------
+
+Control register
+~~~~~~~~~~~~~~~~
+
+**Channel 1**:
+
+.. doxygendefine:: DAC_CR_EN1
+.. doxygendefine:: DAC_CR_BOFF1
+.. doxygendefine:: DAC_CR_TEN1
+.. doxygendefine:: DAC_CR_TSEL1
+.. doxygendefine:: DAC_CR_WAVE1
+.. doxygendefine:: DAC_CR_MAMP1
+.. doxygendefine:: DAC_CR_DMAEN1
+
+**Channel 2**:
+
+.. doxygendefine:: DAC_CR_EN2
+.. doxygendefine:: DAC_CR_BOFF2
+.. doxygendefine:: DAC_CR_TEN2
+.. doxygendefine:: DAC_CR_TSEL2
+.. doxygendefine:: DAC_CR_WAVE2
+.. doxygendefine:: DAC_CR_MAMP2
+.. doxygendefine:: DAC_CR_DMAEN2
+
+Software trigger register
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: DAC_SWTRIGR_SWTRIG1
+.. doxygendefine:: DAC_SWTRIGR_SWTRIG2
+
+Channel 1 12-bit right-aligned data holding register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: DAC_DHR12R1_DACC1DHR
+
+Channel 1 12-bit left-aligned data holding register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: DAC_DHR12L1_DACC1DHR
+
+Channel 1 8-bit left-aligned data holding register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: DAC_DHR8R1_DACC1DHR
+
+Channel 2 12-bit right-aligned data holding register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: DAC_DHR12R2_DACC2DHR
+
+Channel 2 12-bit left-aligned data holding register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: DAC_DHR12L2_DACC2DHR
+
+Channel 2 8-bit left-aligned data holding register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: DAC_DHR8R2_DACC2DHR
+
+Dual DAC 12-bit right-aligned data holding register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: DAC_DHR12RD_DACC1DHR
+.. doxygendefine:: DAC_DHR12RD_DACC2DHR
+
+Dual DAC 12-bit left-aligned data holding register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: DAC_DHR12LD_DACC1DHR
+.. doxygendefine:: DAC_DHR12LD_DACC2DHR
+
+Dual DAC 8-bit left-aligned data holding register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: DAC_DHR8RD_DACC1DHR
+.. doxygendefine:: DAC_DHR8RD_DACC2DHR
+
+Channel 1 data output register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: DAC_DOR1_DACC1DOR
+
+Channel 1 data output register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. doxygendefine:: DAC_DOR2_DACC2DOR
diff --git a/docs/source/libmaple/api/delay.rst b/docs/source/libmaple/api/delay.rst
new file mode 100644
index 0000000..d11496b
--- /dev/null
+++ b/docs/source/libmaple/api/delay.rst
@@ -0,0 +1,11 @@
+.. highlight:: c
+.. _libmaple-delay:
+
+``<libmaple/delay.h>``
+======================
+
+Provides a simple busy-loop delay function. Note that this function
+does not account for time spent in interrupts, so actual delay times
+may vary depending on your application.
+
+.. doxygenfunction:: delay_us
diff --git a/docs/source/libmaple/api/dma.rst b/docs/source/libmaple/api/dma.rst
new file mode 100644
index 0000000..a9893e2
--- /dev/null
+++ b/docs/source/libmaple/api/dma.rst
@@ -0,0 +1,215 @@
+.. highlight:: c
+.. _libmaple-dma:
+
+``dma.h``
+=========
+
+Direct Memory Access (DMA) support.
+
+.. contents:: Contents
+ :local:
+
+Types
+-----
+
+.. doxygenstruct:: dma_reg_map
+.. doxygenstruct:: dma_dev
+.. doxygenstruct:: dma_handler_config
+.. doxygenenum:: dma_mode_flags
+.. doxygenenum:: dma_xfer_size
+.. doxygenenum:: dma_channel
+.. doxygenenum:: dma_priority
+.. doxygenenum:: dma_irq_cause
+.. doxygenstruct:: dma_channel_reg_map
+
+Devices
+-------
+
+.. doxygenvariable:: DMA1
+.. doxygenvariable:: DMA2
+
+Functions
+---------
+
+.. doxygenfunction:: dma_init
+.. doxygenfunction:: dma_setup_transfer
+.. doxygenfunction:: dma_set_num_transfers
+.. doxygenfunction:: dma_set_priority
+.. doxygenfunction:: dma_attach_interrupt
+.. doxygenfunction:: dma_detach_interrupt
+.. doxygenfunction:: dma_get_irq_cause
+.. doxygenfunction:: dma_enable
+.. doxygenfunction:: dma_disable
+.. doxygenfunction:: dma_set_mem_addr
+.. doxygenfunction:: dma_set_per_addr
+.. doxygenfunction:: dma_channel_regs
+.. doxygenfunction:: dma_is_channel_enabled
+.. doxygenfunction:: dma_get_isr_bits
+.. doxygenfunction:: dma_clear_isr_bits
+
+Register Map Base Pointers
+--------------------------
+
+.. doxygendefine:: DMA1_BASE
+.. doxygendefine:: DMA2_BASE
+
+Register Bit Definitions
+------------------------
+
+Interrupt status register
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: DMA_ISR_TEIF7_BIT
+.. doxygendefine:: DMA_ISR_HTIF7_BIT
+.. doxygendefine:: DMA_ISR_TCIF7_BIT
+.. doxygendefine:: DMA_ISR_GIF7_BIT
+.. doxygendefine:: DMA_ISR_TEIF6_BIT
+.. doxygendefine:: DMA_ISR_HTIF6_BIT
+.. doxygendefine:: DMA_ISR_TCIF6_BIT
+.. doxygendefine:: DMA_ISR_GIF6_BIT
+.. doxygendefine:: DMA_ISR_TEIF5_BIT
+.. doxygendefine:: DMA_ISR_HTIF5_BIT
+.. doxygendefine:: DMA_ISR_TCIF5_BIT
+.. doxygendefine:: DMA_ISR_GIF5_BIT
+.. doxygendefine:: DMA_ISR_TEIF4_BIT
+.. doxygendefine:: DMA_ISR_HTIF4_BIT
+.. doxygendefine:: DMA_ISR_TCIF4_BIT
+.. doxygendefine:: DMA_ISR_GIF4_BIT
+.. doxygendefine:: DMA_ISR_TEIF3_BIT
+.. doxygendefine:: DMA_ISR_HTIF3_BIT
+.. doxygendefine:: DMA_ISR_TCIF3_BIT
+.. doxygendefine:: DMA_ISR_GIF3_BIT
+.. doxygendefine:: DMA_ISR_TEIF2_BIT
+.. doxygendefine:: DMA_ISR_HTIF2_BIT
+.. doxygendefine:: DMA_ISR_TCIF2_BIT
+.. doxygendefine:: DMA_ISR_GIF2_BIT
+.. doxygendefine:: DMA_ISR_TEIF1_BIT
+.. doxygendefine:: DMA_ISR_HTIF1_BIT
+.. doxygendefine:: DMA_ISR_TCIF1_BIT
+.. doxygendefine:: DMA_ISR_GIF1_BIT
+
+.. doxygendefine:: DMA_ISR_TEIF7
+.. doxygendefine:: DMA_ISR_HTIF7
+.. doxygendefine:: DMA_ISR_TCIF7
+.. doxygendefine:: DMA_ISR_GIF7
+.. doxygendefine:: DMA_ISR_TEIF6
+.. doxygendefine:: DMA_ISR_HTIF6
+.. doxygendefine:: DMA_ISR_TCIF6
+.. doxygendefine:: DMA_ISR_GIF6
+.. doxygendefine:: DMA_ISR_TEIF5
+.. doxygendefine:: DMA_ISR_HTIF5
+.. doxygendefine:: DMA_ISR_TCIF5
+.. doxygendefine:: DMA_ISR_GIF5
+.. doxygendefine:: DMA_ISR_TEIF4
+.. doxygendefine:: DMA_ISR_HTIF4
+.. doxygendefine:: DMA_ISR_TCIF4
+.. doxygendefine:: DMA_ISR_GIF4
+.. doxygendefine:: DMA_ISR_TEIF3
+.. doxygendefine:: DMA_ISR_HTIF3
+.. doxygendefine:: DMA_ISR_TCIF3
+.. doxygendefine:: DMA_ISR_GIF3
+.. doxygendefine:: DMA_ISR_TEIF2
+.. doxygendefine:: DMA_ISR_HTIF2
+.. doxygendefine:: DMA_ISR_TCIF2
+.. doxygendefine:: DMA_ISR_GIF2
+.. doxygendefine:: DMA_ISR_TEIF1
+.. doxygendefine:: DMA_ISR_HTIF1
+.. doxygendefine:: DMA_ISR_TCIF1
+.. doxygendefine:: DMA_ISR_GIF1
+
+Interrupt flag clear register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: DMA_IFCR_CTEIF7_BIT
+.. doxygendefine:: DMA_IFCR_CHTIF7_BIT
+.. doxygendefine:: DMA_IFCR_CTCIF7_BIT
+.. doxygendefine:: DMA_IFCR_CGIF7_BIT
+.. doxygendefine:: DMA_IFCR_CTEIF6_BIT
+.. doxygendefine:: DMA_IFCR_CHTIF6_BIT
+.. doxygendefine:: DMA_IFCR_CTCIF6_BIT
+.. doxygendefine:: DMA_IFCR_CGIF6_BIT
+.. doxygendefine:: DMA_IFCR_CTEIF5_BIT
+.. doxygendefine:: DMA_IFCR_CHTIF5_BIT
+.. doxygendefine:: DMA_IFCR_CTCIF5_BIT
+.. doxygendefine:: DMA_IFCR_CGIF5_BIT
+.. doxygendefine:: DMA_IFCR_CTEIF4_BIT
+.. doxygendefine:: DMA_IFCR_CHTIF4_BIT
+.. doxygendefine:: DMA_IFCR_CTCIF4_BIT
+.. doxygendefine:: DMA_IFCR_CGIF4_BIT
+.. doxygendefine:: DMA_IFCR_CTEIF3_BIT
+.. doxygendefine:: DMA_IFCR_CHTIF3_BIT
+.. doxygendefine:: DMA_IFCR_CTCIF3_BIT
+.. doxygendefine:: DMA_IFCR_CGIF3_BIT
+.. doxygendefine:: DMA_IFCR_CTEIF2_BIT
+.. doxygendefine:: DMA_IFCR_CHTIF2_BIT
+.. doxygendefine:: DMA_IFCR_CTCIF2_BIT
+.. doxygendefine:: DMA_IFCR_CGIF2_BIT
+.. doxygendefine:: DMA_IFCR_CTEIF1_BIT
+.. doxygendefine:: DMA_IFCR_CHTIF1_BIT
+.. doxygendefine:: DMA_IFCR_CTCIF1_BIT
+.. doxygendefine:: DMA_IFCR_CGIF1_BIT
+
+.. doxygendefine:: DMA_IFCR_CTEIF7
+.. doxygendefine:: DMA_IFCR_CHTIF7
+.. doxygendefine:: DMA_IFCR_CTCIF7
+.. doxygendefine:: DMA_IFCR_CGIF7
+.. doxygendefine:: DMA_IFCR_CTEIF6
+.. doxygendefine:: DMA_IFCR_CHTIF6
+.. doxygendefine:: DMA_IFCR_CTCIF6
+.. doxygendefine:: DMA_IFCR_CGIF6
+.. doxygendefine:: DMA_IFCR_CTEIF5
+.. doxygendefine:: DMA_IFCR_CHTIF5
+.. doxygendefine:: DMA_IFCR_CTCIF5
+.. doxygendefine:: DMA_IFCR_CGIF5
+.. doxygendefine:: DMA_IFCR_CTEIF4
+.. doxygendefine:: DMA_IFCR_CHTIF4
+.. doxygendefine:: DMA_IFCR_CTCIF4
+.. doxygendefine:: DMA_IFCR_CGIF4
+.. doxygendefine:: DMA_IFCR_CTEIF3
+.. doxygendefine:: DMA_IFCR_CHTIF3
+.. doxygendefine:: DMA_IFCR_CTCIF3
+.. doxygendefine:: DMA_IFCR_CGIF3
+.. doxygendefine:: DMA_IFCR_CTEIF2
+.. doxygendefine:: DMA_IFCR_CHTIF2
+.. doxygendefine:: DMA_IFCR_CTCIF2
+.. doxygendefine:: DMA_IFCR_CGIF2
+.. doxygendefine:: DMA_IFCR_CTEIF1
+.. doxygendefine:: DMA_IFCR_CHTIF1
+.. doxygendefine:: DMA_IFCR_CTCIF1
+.. doxygendefine:: DMA_IFCR_CGIF1
+
+Channel configuration register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: DMA_CCR_MEM2MEM_BIT
+.. doxygendefine:: DMA_CCR_MINC_BIT
+.. doxygendefine:: DMA_CCR_PINC_BIT
+.. doxygendefine:: DMA_CCR_CIRC_BIT
+.. doxygendefine:: DMA_CCR_DIR_BIT
+.. doxygendefine:: DMA_CCR_TEIE_BIT
+.. doxygendefine:: DMA_CCR_HTIE_BIT
+.. doxygendefine:: DMA_CCR_TCIE_BIT
+.. doxygendefine:: DMA_CCR_EN_BIT
+
+.. doxygendefine:: DMA_CCR_MEM2MEM
+.. doxygendefine:: DMA_CCR_PL
+.. doxygendefine:: DMA_CCR_PL_LOW
+.. doxygendefine:: DMA_CCR_PL_MEDIUM
+.. doxygendefine:: DMA_CCR_PL_HIGH
+.. doxygendefine:: DMA_CCR_PL_VERY_HIGH
+.. doxygendefine:: DMA_CCR_MSIZE
+.. doxygendefine:: DMA_CCR_MSIZE_8BITS
+.. doxygendefine:: DMA_CCR_MSIZE_16BITS
+.. doxygendefine:: DMA_CCR_MSIZE_32BITS
+.. doxygendefine:: DMA_CCR_PSIZE
+.. doxygendefine:: DMA_CCR_PSIZE_8BITS
+.. doxygendefine:: DMA_CCR_PSIZE_16BITS
+.. doxygendefine:: DMA_CCR_PSIZE_32BITS
+.. doxygendefine:: DMA_CCR_MINC
+.. doxygendefine:: DMA_CCR_PINC
+.. doxygendefine:: DMA_CCR_CIRC
+.. doxygendefine:: DMA_CCR_DIR
+.. doxygendefine:: DMA_CCR_TEIE
+.. doxygendefine:: DMA_CCR_HTIE
+.. doxygendefine:: DMA_CCR_TCIE
+.. doxygendefine:: DMA_CCR_EN
diff --git a/docs/source/libmaple/api/exti.rst b/docs/source/libmaple/api/exti.rst
new file mode 100644
index 0000000..1038fbf
--- /dev/null
+++ b/docs/source/libmaple/api/exti.rst
@@ -0,0 +1,37 @@
+.. highlight:: c
+.. _libmaple-exti:
+
+``exti.h``
+==========
+
+:ref:`External interrupt <external-interrupts>` support.
+
+.. contents:: Contents
+ :local:
+
+Types
+-----
+
+.. doxygenstruct:: exti_reg_map
+.. doxygenenum:: exti_trigger_mode
+
+Devices
+-------
+
+None at this time.
+
+Functions
+---------
+
+.. doxygenfunction:: exti_attach_interrupt
+.. doxygenfunction:: exti_detach_interrupt
+
+Register Map Base Pointers
+--------------------------
+
+.. doxygendefine:: EXTI_BASE
+
+Register Bit Definitions
+------------------------
+
+None at this time.
diff --git a/docs/source/libmaple/api/flash.rst b/docs/source/libmaple/api/flash.rst
new file mode 100644
index 0000000..52ff4d2
--- /dev/null
+++ b/docs/source/libmaple/api/flash.rst
@@ -0,0 +1,249 @@
+.. highlight:: c
+.. _libmaple-flash:
+
+``<libmaple/flash.h>``
+======================
+
+Flash memory support.
+
+The built-in Flash on different STM32 MCUs varies in terms of its
+eraseable page/sector size and read/write protections. There isn't
+currently much support for dealing with this. This header is mostly
+useful for its functions that control Flash features which affect
+system performance, like wait states and prefetch buffers.
+
+.. contents:: Contents
+ :local:
+
+Devices
+-------
+
+None at this time.
+
+Functions
+---------
+
+The following functions can be used to portably manipulate Flash memory.
+
+.. doxygenfunction:: flash_set_latency
+.. doxygenfunction:: flash_enable_features
+.. doxygenfunction:: flash_enable_prefetch
+
+Register Maps
+-------------
+
+Register maps vary by target. The base pointer is always ``FLASH_BASE``.
+
+Base Pointer
+~~~~~~~~~~~~
+
+.. doxygendefine:: FLASH_BASE
+
+STM32F1 targets
+~~~~~~~~~~~~~~~
+
+.. doxygenstruct:: stm32f1::flash_reg_map
+
+STM32F2 targets
+~~~~~~~~~~~~~~~
+
+.. doxygenstruct:: stm32f2::flash_reg_map
+
+Register Bit Definitions
+------------------------
+
+These are given as source code. Available register bit definitions
+vary by target.
+
+STM32F1 Targets
+~~~~~~~~~~~~~~~
+
+::
+
+ /* Access control register */
+
+ #define FLASH_ACR_PRFTBS_BIT 5
+ #define FLASH_ACR_PRFTBE_BIT 4
+ #define FLASH_ACR_HLFCYA_BIT 3
+
+ #define FLASH_ACR_PRFTBS (1U << FLASH_ACR_PRFTBS_BIT)
+ #define FLASH_ACR_PRFTBE (1U << FLASH_ACR_PRFTBE_BIT)
+ #define FLASH_ACR_HLFCYA (1U << FLASH_ACR_HLFCYA_BIT)
+ #define FLASH_ACR_LATENCY 0x7
+
+ /* Status register */
+
+ #define FLASH_SR_EOP_BIT 5
+ #define FLASH_SR_WRPRTERR_BIT 4
+ #define FLASH_SR_PGERR_BIT 2
+ #define FLASH_SR_BSY_BIT 0
+
+ #define FLASH_SR_EOP (1U << FLASH_SR_EOP_BIT)
+ #define FLASH_SR_WRPRTERR (1U << FLASH_SR_WRPRTERR_BIT)
+ #define FLASH_SR_PGERR (1U << FLASH_SR_PGERR_BIT)
+ #define FLASH_SR_BSY (1U << FLASH_SR_BSY_BIT)
+
+ /* Control register */
+
+ #define FLASH_CR_EOPIE_BIT 12
+ #define FLASH_CR_ERRIE_BIT 10
+ #define FLASH_CR_OPTWRE_BIT 9
+ #define FLASH_CR_LOCK_BIT 7
+ #define FLASH_CR_STRT_BIT 6
+ #define FLASH_CR_OPTER_BIT 5
+ #define FLASH_CR_OPTPG_BIT 4
+ #define FLASH_CR_MER_BIT 2
+ #define FLASH_CR_PER_BIT 1
+ #define FLASH_CR_PG_BIT 0
+
+ #define FLASH_CR_EOPIE (1U << FLASH_CR_EOPIE_BIT)
+ #define FLASH_CR_ERRIE (1U << FLASH_CR_ERRIE_BIT)
+ #define FLASH_CR_OPTWRE (1U << FLASH_CR_OPTWRE_BIT)
+ #define FLASH_CR_LOCK (1U << FLASH_CR_LOCK_BIT)
+ #define FLASH_CR_STRT (1U << FLASH_CR_STRT_BIT)
+ #define FLASH_CR_OPTER (1U << FLASH_CR_OPTER_BIT)
+ #define FLASH_CR_OPTPG (1U << FLASH_CR_OPTPG_BIT)
+ #define FLASH_CR_MER (1U << FLASH_CR_MER_BIT)
+ #define FLASH_CR_PER (1U << FLASH_CR_PER_BIT)
+ #define FLASH_CR_PG (1U << FLASH_CR_PG_BIT)
+
+ /* Option byte register */
+
+ #define FLASH_OBR_nRST_STDBY_BIT 4
+ #define FLASH_OBR_nRST_STOP_BIT 3
+ #define FLASH_OBR_WDG_SW_BIT 2
+ #define FLASH_OBR_RDPRT_BIT 1
+ #define FLASH_OBR_OPTERR_BIT 0
+
+ #define FLASH_OBR_DATA1 (0xFF << 18)
+ #define FLASH_OBR_DATA0 (0xFF << 10)
+ #define FLASH_OBR_USER 0x3FF
+ #define FLASH_OBR_nRST_STDBY (1U << FLASH_OBR_nRST_STDBY_BIT)
+ #define FLASH_OBR_nRST_STOP (1U << FLASH_OBR_nRST_STOP_BIT)
+ #define FLASH_OBR_WDG_SW (1U << FLASH_OBR_WDG_SW_BIT)
+ #define FLASH_OBR_RDPRT (1U << FLASH_OBR_RDPRT_BIT)
+ #define FLASH_OBR_OPTERR (1U << FLASH_OBR_OPTERR_BIT)
+
+STM32F2 Targets
+~~~~~~~~~~~~~~~
+
+::
+
+ /* 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)
diff --git a/docs/source/libmaple/api/fsmc.rst b/docs/source/libmaple/api/fsmc.rst
new file mode 100644
index 0000000..e2bf87a
--- /dev/null
+++ b/docs/source/libmaple/api/fsmc.rst
@@ -0,0 +1,235 @@
+.. highlight:: c
+.. _libmaple-fsmc:
+
+``<libmaple/fsmc.h>``
+=====================
+
+Flexible Static Memory Controller (FSMC) support. The FSMC peripheral
+is only available on some targets. Including this header on a target
+without an FSMC will cause a compilation error. Check your target's
+documentation to determine if it's available. You can also use
+:ref:`STM32_HAVE_FSMC <libmaple-stm32-STM32_HAVE_FSMC>` from
+``<libmaple/stm32.h>`` to determine whether your target has an FSMC at
+build time.
+
+All functionality documented here is portable.
+
+.. contents:: Contents
+ :local:
+
+Usage Note
+----------
+
+FSMC support is fairly limited at this time. Current Leaflabs boards
+only use the FSMC to interface with external SRAM chips, so that's
+what there's the most support for (:ref:`patches welcome!
+<libmaple-contributing>`). Even for use with SRAM, you will still need
+to program some registers directly.
+
+To use the FSMC with an SRAM chip, first call
+:ref:`fsmc_sram_init_gpios() <libmaple-fsmc-fsmc_sram_init_gpios>` to
+configure its data, address, and control lines. Then, turn on the
+FSMC clock (by calling :ref:`rcc_clk_enable(RCC_FSMC)
+<libmaple-rcc-rcc_clk_enable>`). You can then configure the relevant
+:ref:`fsmc_nor_psram_reg_map <libmaple-fsmc-fsmc_nor_psram_reg_map>`
+``BCR`` register yourself for the SRAM chip you are using.
+
+You can additionally use :ref:`fsmc_nor_psram_set_datast()
+<libmaple-fsmc-fsmc_nor_psram_set_datast>` and
+:ref:`fsmc_nor_psram_set_datast() <libmaple-fsmc-fsmc_nor_psram_set_datast>`
+to control read/write timing.
+
+Devices
+-------
+
+None at this time.
+
+Functions
+---------
+
+.. _libmaple-fsmc-fsmc_sram_init_gpios:
+.. doxygenfunction:: fsmc_sram_init_gpios
+.. _libmaple-fsmc-fsmc_nor_psram_set_datast:
+.. doxygenfunction:: fsmc_nor_psram_set_datast
+.. _libmaple-fsmc-fsmc_nor_psram_set_addset:
+.. doxygenfunction:: fsmc_nor_psram_set_addset
+
+Register Maps
+-------------
+
+The general purpose register map type is ``fsmc_reg_map``; its base
+pointer is ``FSMC_BASE``. The ``fsmc_nor_psram_reg_map`` type is for
+use configuring the registers for an individual NOR/PSRAM region
+(``FSMC_BCRx``, ``FSMC_BTRx``, and ``FSMC_BWTRx``); the relevant base
+pointers are ``FSMC_NOR_PSRAM_REGION1`` through
+``FSMC_NOR_PSRAM_REGION4``.
+
+.. doxygendefine:: FSMC_BASE
+
+.. doxygendefine:: FSMC_NOR_PSRAM1_BASE
+.. doxygendefine:: FSMC_NOR_PSRAM2_BASE
+.. doxygendefine:: FSMC_NOR_PSRAM3_BASE
+.. doxygendefine:: FSMC_NOR_PSRAM4_BASE
+
+.. doxygenstruct:: fsmc_reg_map
+.. _libmaple-fsmc-fsmc_nor_psram_reg_map:
+.. doxygenstruct:: fsmc_nor_psram_reg_map
+
+Memory Bank Boundary Addresses
+------------------------------
+
+Reading and writing data on an external memory chip using FSMC is done
+by reading and writing from addresses in special memory-mapped
+sections of the address space called *memory banks*.
+
+This is convenient, since it implies that the usual load and store
+instructions used for I/O with the internal SRAM are also used to
+perform bus transactions with the external memory chip. (Which means
+you can use ``memcpy()`` etc. on external memory.)
+
+Pointers to the memory banks' base addresses are given by the
+following macros.
+
+.. doxygendefine:: FSMC_BANK1
+.. doxygendefine:: FSMC_BANK2
+.. doxygendefine:: FSMC_BANK3
+.. doxygendefine:: FSMC_BANK4
+
+.. doxygendefine:: FSMC_NOR_PSRAM_REGION1
+.. doxygendefine:: FSMC_NOR_PSRAM_REGION2
+.. doxygendefine:: FSMC_NOR_PSRAM_REGION3
+.. doxygendefine:: FSMC_NOR_PSRAM_REGION4
+
+Register Bit Definitions
+------------------------
+
+These are given as source code.
+
+::
+
+ /* NOR/PSRAM chip-select control registers */
+
+ #define FSMC_BCR_CBURSTRW_BIT 19
+ #define FSMC_BCR_ASYNCWAIT_BIT 15
+ #define FSMC_BCR_EXTMOD_BIT 14
+ #define FSMC_BCR_WAITEN_BIT 13
+ #define FSMC_BCR_WREN_BIT 12
+ #define FSMC_BCR_WAITCFG_BIT 11
+ #define FSMC_BCR_WRAPMOD_BIT 10
+ #define FSMC_BCR_WAITPOL_BIT 9
+ #define FSMC_BCR_BURSTEN_BIT 8
+ #define FSMC_BCR_FACCEN_BIT 6
+ #define FSMC_BCR_MUXEN_BIT 1
+ #define FSMC_BCR_MBKEN_BIT 0
+
+ #define FSMC_BCR_CBURSTRW (1U << FSMC_BCR_CBURSTRW_BIT)
+ #define FSMC_BCR_ASYNCWAIT (1U << FSMC_BCR_ASYNCWAIT_BIT)
+ #define FSMC_BCR_EXTMOD (1U << FSMC_BCR_EXTMOD_BIT)
+ #define FSMC_BCR_WAITEN (1U << FSMC_BCR_WAITEN_BIT)
+ #define FSMC_BCR_WREN (1U << FSMC_BCR_WREN_BIT)
+ #define FSMC_BCR_WAITCFG (1U << FSMC_BCR_WAITCFG_BIT)
+ #define FSMC_BCR_WRAPMOD (1U << FSMC_BCR_WRAPMOD_BIT)
+ #define FSMC_BCR_WAITPOL (1U << FSMC_BCR_WAITPOL_BIT)
+ #define FSMC_BCR_BURSTEN (1U << FSMC_BCR_BURSTEN_BIT)
+ #define FSMC_BCR_FACCEN (1U << FSMC_BCR_FACCEN_BIT)
+ #define FSMC_BCR_MWID (0x3 << 4)
+ #define FSMC_BCR_MWID_8BITS (0x0 << 4)
+ #define FSMC_BCR_MWID_16BITS (0x1 << 4)
+ #define FSMC_BCR_MTYP (0x3 << 2)
+ #define FSMC_BCR_MTYP_SRAM (0x0 << 2)
+ #define FSMC_BCR_MTYP_PSRAM (0x1 << 2)
+ #define FSMC_BCR_MTYP_NOR_FLASH (0x2 << 2)
+ #define FSMC_BCR_MUXEN (1U << FSMC_BCR_MUXEN_BIT)
+ #define FSMC_BCR_MBKEN (1U << FSMC_BCR_MBKEN_BIT)
+
+ /* SRAM/NOR-Flash chip-select timing registers */
+
+ #define FSMC_BTR_ACCMOD (0x3 << 28)
+ #define FSMC_BTR_ACCMOD_A (0x0 << 28)
+ #define FSMC_BTR_ACCMOD_B (0x1 << 28)
+ #define FSMC_BTR_ACCMOD_C (0x2 << 28)
+ #define FSMC_BTR_ACCMOD_D (0x3 << 28)
+ #define FSMC_BTR_DATLAT (0xF << 24)
+ #define FSMC_BTR_CLKDIV (0xF << 20)
+ #define FSMC_BTR_BUSTURN (0xF << 16)
+ #define FSMC_BTR_DATAST (0xFF << 8)
+ #define FSMC_BTR_ADDHLD (0xF << 4)
+ #define FSMC_BTR_ADDSET 0xF
+
+ /* SRAM/NOR-Flash write timing registers */
+
+ #define FSMC_BWTR_ACCMOD (0x3 << 28)
+ #define FSMC_BWTR_ACCMOD_A (0x0 << 28)
+ #define FSMC_BWTR_ACCMOD_B (0x1 << 28)
+ #define FSMC_BWTR_ACCMOD_C (0x2 << 28)
+ #define FSMC_BWTR_ACCMOD_D (0x3 << 28)
+ #define FSMC_BWTR_DATLAT (0xF << 24)
+ #define FSMC_BWTR_CLKDIV (0xF << 20)
+ #define FSMC_BWTR_DATAST (0xFF << 8)
+ #define FSMC_BWTR_ADDHLD (0xF << 4)
+ #define FSMC_BWTR_ADDSET 0xF
+
+ /* NAND Flash/PC Card controller registers */
+
+ #define FSMC_PCR_ECCEN_BIT 6
+ #define FSMC_PCR_PTYP_BIT 3
+ #define FSMC_PCR_PBKEN_BIT 2
+ #define FSMC_PCR_PWAITEN_BIT 1
+
+ #define FSMC_PCR_ECCPS (0x7 << 17)
+ #define FSMC_PCR_ECCPS_256B (0x0 << 17)
+ #define FSMC_PCR_ECCPS_512B (0x1 << 17)
+ #define FSMC_PCR_ECCPS_1024B (0x2 << 17)
+ #define FSMC_PCR_ECCPS_2048B (0x3 << 17)
+ #define FSMC_PCR_ECCPS_4096B (0x4 << 17)
+ #define FSMC_PCR_ECCPS_8192B (0x5 << 17)
+ #define FSMC_PCR_TAR (0xF << 13)
+ #define FSMC_PCR_TCLR (0xF << 9)
+ #define FSMC_PCR_ECCEN (1U << FSMC_PCR_ECCEN_BIT)
+ #define FSMC_PCR_PWID (0x3 << 4)
+ #define FSMC_PCR_PWID_8BITS (0x0 << 4)
+ #define FSMC_PCR_PWID_16BITS (0x1 << 4)
+ #define FSMC_PCR_PTYP (1U << FSMC_PCR_PTYP_BIT)
+ #define FSMC_PCR_PTYP_PC_CF_PCMCIA (0x0 << FSMC_PCR_PTYP_BIT)
+ #define FSMC_PCR_PTYP_NAND (0x1 << FSMC_PCR_PTYP_BIT)
+ #define FSMC_PCR_PBKEN (1U << FSMC_PCR_PBKEN_BIT)
+ #define FSMC_PCR_PWAITEN (1U << FSMC_PCR_PWAITEN_BIT)
+
+ /* FIFO status and interrupt registers */
+
+ #define FSMC_SR_FEMPT_BIT 6
+ #define FSMC_SR_IFEN_BIT 5
+ #define FSMC_SR_ILEN_BIT 4
+ #define FSMC_SR_IREN_BIT 3
+ #define FSMC_SR_IFS_BIT 2
+ #define FSMC_SR_ILS_BIT 1
+ #define FSMC_SR_IRS_BIT 0
+
+ #define FSMC_SR_FEMPT (1U << FSMC_SR_FEMPT_BIT)
+ #define FSMC_SR_IFEN (1U << FSMC_SR_IFEN_BIT)
+ #define FSMC_SR_ILEN (1U << FSMC_SR_ILEN_BIT)
+ #define FSMC_SR_IREN (1U << FSMC_SR_IREN_BIT)
+ #define FSMC_SR_IFS (1U << FSMC_SR_IFS_BIT)
+ #define FSMC_SR_ILS (1U << FSMC_SR_ILS_BIT)
+ #define FSMC_SR_IRS (1U << FSMC_SR_IRS_BIT)
+
+ /* Common memory space timing registers */
+
+ #define FSMC_PMEM_MEMHIZ (0xFF << 24)
+ #define FSMC_PMEM_MEMHOLD (0xFF << 16)
+ #define FSMC_PMEM_MEMWAIT (0xFF << 8)
+ #define FSMC_PMEM_MEMSET 0xFF
+
+ /* Attribute memory space timing registers */
+
+ #define FSMC_PATT_ATTHIZ (0xFF << 24)
+ #define FSMC_PATT_ATTHOLD (0xFF << 16)
+ #define FSMC_PATT_ATTWAIT (0xFF << 8)
+ #define FSMC_PATT_ATTSET 0xFF
+
+ /* I/O space timing register 4 */
+
+ #define FSMC_PIO_IOHIZ (0xFF << 24)
+ #define FSMC_PIO_IOHOLD (0xFF << 16)
+ #define FSMC_PIO_IOWAIT (0xFF << 8)
+ #define FSMC_PIO_IOSET 0xF
diff --git a/docs/source/libmaple/api/gpio.rst b/docs/source/libmaple/api/gpio.rst
new file mode 100644
index 0000000..faf0ad2
--- /dev/null
+++ b/docs/source/libmaple/api/gpio.rst
@@ -0,0 +1,243 @@
+.. highlight:: c
+.. _libmaple-gpio:
+
+``gpio.h``
+==========
+
+General Purpose Input/Output (GPIO) port and Alternate Function
+Input/Output (AFIO) support.
+
+.. contents:: Contents
+ :local:
+
+Types
+-----
+
+.. doxygenstruct:: gpio_reg_map
+.. doxygenstruct:: gpio_dev
+.. doxygenenum:: gpio_pin_mode
+
+.. doxygenstruct:: afio_reg_map
+.. doxygenenum:: afio_exti_port
+.. doxygenenum:: afio_exti_num
+.. doxygenenum:: afio_remap_peripheral
+.. doxygenenum:: afio_debug_cfg
+
+Devices
+-------
+
+.. doxygenvariable:: GPIOA
+.. doxygenvariable:: GPIOB
+.. doxygenvariable:: GPIOC
+.. doxygenvariable:: GPIOD
+.. doxygenvariable:: GPIOE
+.. doxygenvariable:: GPIOF
+.. doxygenvariable:: GPIOG
+
+Functions
+---------
+
+.. doxygenfunction:: gpio_init
+.. doxygenfunction:: gpio_init_all
+.. doxygenfunction:: gpio_set_mode
+.. doxygenfunction:: gpio_exti_port
+.. doxygenfunction:: gpio_write_bit
+.. doxygenfunction:: gpio_read_bit
+.. doxygenfunction:: gpio_toggle_bit
+
+.. doxygenfunction:: afio_init
+.. doxygenfunction:: afio_exti_select
+
+.. _gpio-h-afio-remap:
+.. doxygenfunction:: afio_remap
+.. doxygenfunction:: afio_cfg_debug_ports
+
+Register Map Base Pointers
+--------------------------
+
+.. doxygendefine:: GPIOA_BASE
+.. doxygendefine:: GPIOB_BASE
+.. doxygendefine:: GPIOC_BASE
+.. doxygendefine:: GPIOD_BASE
+.. doxygendefine:: GPIOE_BASE
+.. doxygendefine:: GPIOF_BASE
+.. doxygendefine:: GPIOG_BASE
+
+.. doxygendefine:: AFIO_BASE
+
+Register Bit Definitions
+------------------------
+
+GPIO Control Registers
+~~~~~~~~~~~~~~~~~~~~~~
+
+These values apply to both the low and high configuration registers
+(ST RM0008: GPIOx_CRL and GPIOx_CRH). You can shift them right by the
+appropriate number of bits for the GPIO port bit you're interested in
+to obtain a bit mask.
+
+For example, to mask out just the value of GPIOA_CRH_CNF12, note that
+GPIO port bit 12's configuration starts at bit 18 in the corresponding
+CRH. Thus, an appropriate mask is ``GPIOA_BASE->CRH & (GPIO_CR_CNF <<
+18)``.
+
+.. doxygendefine:: GPIO_CR_CNF_INPUT_ANALOG
+.. doxygendefine:: GPIO_CR_CNF_INPUT_FLOATING
+.. doxygendefine:: GPIO_CR_CNF_INPUT_PU_PD
+.. doxygendefine:: GPIO_CR_CNF_OUTPUT_PP
+.. doxygendefine:: GPIO_CR_CNF_OUTPUT_OD
+.. doxygendefine:: GPIO_CR_CNF_AF_OUTPUT_PP
+.. doxygendefine:: GPIO_CR_CNF_AF_OUTPUT_OD
+.. doxygendefine:: GPIO_CR_MODE_INPUT
+.. doxygendefine:: GPIO_CR_MODE_OUTPUT_10MHZ
+.. doxygendefine:: GPIO_CR_MODE_OUTPUT_2MHZ
+.. doxygendefine:: GPIO_CR_MODE_OUTPUT_50MHZ
+
+Event Control Register
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: AFIO_EVCR_EVOE
+.. doxygendefine:: AFIO_EVCR_PORT_PA
+.. doxygendefine:: AFIO_EVCR_PORT_PB
+.. doxygendefine:: AFIO_EVCR_PORT_PC
+.. doxygendefine:: AFIO_EVCR_PORT_PD
+.. doxygendefine:: AFIO_EVCR_PORT_PE
+.. doxygendefine:: AFIO_EVCR_PIN_0
+.. doxygendefine:: AFIO_EVCR_PIN_1
+.. doxygendefine:: AFIO_EVCR_PIN_2
+.. doxygendefine:: AFIO_EVCR_PIN_3
+.. doxygendefine:: AFIO_EVCR_PIN_4
+.. doxygendefine:: AFIO_EVCR_PIN_5
+.. doxygendefine:: AFIO_EVCR_PIN_6
+.. doxygendefine:: AFIO_EVCR_PIN_7
+.. doxygendefine:: AFIO_EVCR_PIN_8
+.. doxygendefine:: AFIO_EVCR_PIN_9
+.. doxygendefine:: AFIO_EVCR_PIN_10
+.. doxygendefine:: AFIO_EVCR_PIN_11
+.. doxygendefine:: AFIO_EVCR_PIN_12
+.. doxygendefine:: AFIO_EVCR_PIN_13
+.. doxygendefine:: AFIO_EVCR_PIN_14
+.. doxygendefine:: AFIO_EVCR_PIN_15
+
+AF Remap and Debug I/O Configuration Register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: AFIO_MAPR_SWJ_CFG
+.. doxygendefine:: AFIO_MAPR_SWJ_CFG_FULL_SWJ
+.. doxygendefine:: AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST
+.. doxygendefine:: AFIO_MAPR_SWJ_CFG_NO_JTAG_SW
+.. doxygendefine:: AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW
+.. doxygendefine:: AFIO_MAPR_ADC2_ETRGREG_REMAP
+.. doxygendefine:: AFIO_MAPR_ADC2_ETRGINJ_REMAP
+.. doxygendefine:: AFIO_MAPR_ADC1_ETRGREG_REMAP
+.. doxygendefine:: AFIO_MAPR_ADC1_ETRGINJ_REMAP
+.. doxygendefine:: AFIO_MAPR_TIM5CH4_IREMAP
+.. doxygendefine:: AFIO_MAPR_PD01_REMAP
+.. doxygendefine:: AFIO_MAPR_CAN_REMAP
+.. doxygendefine:: AFIO_MAPR_CAN_REMAP_NONE
+.. doxygendefine:: AFIO_MAPR_CAN_REMAP_PB8_PB9
+.. doxygendefine:: AFIO_MAPR_CAN_REMAP_PD0_PD1
+.. doxygendefine:: AFIO_MAPR_TIM4_REMAP
+.. doxygendefine:: AFIO_MAPR_TIM3_REMAP
+.. doxygendefine:: AFIO_MAPR_TIM3_REMAP_NONE
+.. doxygendefine:: AFIO_MAPR_TIM3_REMAP_PARTIAL
+.. doxygendefine:: AFIO_MAPR_TIM3_REMAP_FULL
+.. doxygendefine:: AFIO_MAPR_TIM2_REMAP
+.. doxygendefine:: AFIO_MAPR_TIM2_REMAP_NONE
+.. doxygendefine:: AFIO_MAPR_TIM2_REMAP_PA15_PB3_PA2_PA3
+.. doxygendefine:: AFIO_MAPR_TIM2_REMAP_PA0_PA1_PB10_PB11
+.. doxygendefine:: AFIO_MAPR_TIM2_REMAP_FULL
+.. doxygendefine:: AFIO_MAPR_TIM1_REMAP
+.. doxygendefine:: AFIO_MAPR_TIM1_REMAP_NONE
+.. doxygendefine:: AFIO_MAPR_TIM1_REMAP_PARTIAL
+.. doxygendefine:: AFIO_MAPR_TIM1_REMAP_FULL
+.. doxygendefine:: AFIO_MAPR_USART3_REMAP
+.. doxygendefine:: AFIO_MAPR_USART3_REMAP_NONE
+.. doxygendefine:: AFIO_MAPR_USART3_REMAP_PARTIAL
+.. doxygendefine:: AFIO_MAPR_USART3_REMAP_FULL
+.. doxygendefine:: AFIO_MAPR_USART2_REMAP
+.. doxygendefine:: AFIO_MAPR_USART1_REMAP
+.. doxygendefine:: AFIO_MAPR_I2C1_REMAP
+.. doxygendefine:: AFIO_MAPR_SPI1_REMAP
+
+External Interrupt Configuration Register 1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: AFIO_EXTICR1_EXTI3
+.. doxygendefine:: AFIO_EXTICR1_EXTI3_PA
+.. doxygendefine:: AFIO_EXTICR1_EXTI3_PB
+.. doxygendefine:: AFIO_EXTICR1_EXTI3_PC
+.. doxygendefine:: AFIO_EXTICR1_EXTI3_PD
+.. doxygendefine:: AFIO_EXTICR1_EXTI3_PE
+.. doxygendefine:: AFIO_EXTICR1_EXTI3_PF
+.. doxygendefine:: AFIO_EXTICR1_EXTI3_PG
+.. doxygendefine:: AFIO_EXTICR1_EXTI2
+.. doxygendefine:: AFIO_EXTICR1_EXTI2_PA
+.. doxygendefine:: AFIO_EXTICR1_EXTI2_PB
+.. doxygendefine:: AFIO_EXTICR1_EXTI2_PC
+.. doxygendefine:: AFIO_EXTICR1_EXTI2_PD
+.. doxygendefine:: AFIO_EXTICR1_EXTI2_PE
+.. doxygendefine:: AFIO_EXTICR1_EXTI2_PF
+.. doxygendefine:: AFIO_EXTICR1_EXTI2_PG
+.. doxygendefine:: AFIO_EXTICR1_EXTI1
+.. doxygendefine:: AFIO_EXTICR1_EXTI1_PA
+.. doxygendefine:: AFIO_EXTICR1_EXTI1_PB
+.. doxygendefine:: AFIO_EXTICR1_EXTI1_PC
+.. doxygendefine:: AFIO_EXTICR1_EXTI1_PD
+.. doxygendefine:: AFIO_EXTICR1_EXTI1_PE
+.. doxygendefine:: AFIO_EXTICR1_EXTI1_PF
+.. doxygendefine:: AFIO_EXTICR1_EXTI1_PG
+.. doxygendefine:: AFIO_EXTICR1_EXTI0
+.. doxygendefine:: AFIO_EXTICR1_EXTI0_PA
+.. doxygendefine:: AFIO_EXTICR1_EXTI0_PB
+.. doxygendefine:: AFIO_EXTICR1_EXTI0_PC
+.. doxygendefine:: AFIO_EXTICR1_EXTI0_PD
+.. doxygendefine:: AFIO_EXTICR1_EXTI0_PE
+.. doxygendefine:: AFIO_EXTICR1_EXTI0_PF
+.. doxygendefine:: AFIO_EXTICR1_EXTI0_PG
+
+External Interrupt Configuration Register 2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: AFIO_EXTICR2_EXTI7
+.. doxygendefine:: AFIO_EXTICR2_EXTI7_PA
+.. doxygendefine:: AFIO_EXTICR2_EXTI7_PB
+.. doxygendefine:: AFIO_EXTICR2_EXTI7_PC
+.. doxygendefine:: AFIO_EXTICR2_EXTI7_PD
+.. doxygendefine:: AFIO_EXTICR2_EXTI7_PE
+.. doxygendefine:: AFIO_EXTICR2_EXTI7_PF
+.. doxygendefine:: AFIO_EXTICR2_EXTI7_PG
+.. doxygendefine:: AFIO_EXTICR2_EXTI6
+.. doxygendefine:: AFIO_EXTICR2_EXTI6_PA
+.. doxygendefine:: AFIO_EXTICR2_EXTI6_PB
+.. doxygendefine:: AFIO_EXTICR2_EXTI6_PC
+.. doxygendefine:: AFIO_EXTICR2_EXTI6_PD
+.. doxygendefine:: AFIO_EXTICR2_EXTI6_PE
+.. doxygendefine:: AFIO_EXTICR2_EXTI6_PF
+.. doxygendefine:: AFIO_EXTICR2_EXTI6_PG
+.. doxygendefine:: AFIO_EXTICR2_EXTI5
+.. doxygendefine:: AFIO_EXTICR2_EXTI5_PA
+.. doxygendefine:: AFIO_EXTICR2_EXTI5_PB
+.. doxygendefine:: AFIO_EXTICR2_EXTI5_PC
+.. doxygendefine:: AFIO_EXTICR2_EXTI5_PD
+.. doxygendefine:: AFIO_EXTICR2_EXTI5_PE
+.. doxygendefine:: AFIO_EXTICR2_EXTI5_PF
+.. doxygendefine:: AFIO_EXTICR2_EXTI5_PG
+.. doxygendefine:: AFIO_EXTICR2_EXTI4
+.. doxygendefine:: AFIO_EXTICR2_EXTI4_PA
+.. doxygendefine:: AFIO_EXTICR2_EXTI4_PB
+.. doxygendefine:: AFIO_EXTICR2_EXTI4_PC
+.. doxygendefine:: AFIO_EXTICR2_EXTI4_PD
+.. doxygendefine:: AFIO_EXTICR2_EXTI4_PE
+.. doxygendefine:: AFIO_EXTICR2_EXTI4_PF
+.. doxygendefine:: AFIO_EXTICR2_EXTI4_PG
+
+AF Remap and Debug I/O Configuration Register 2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: AFIO_MAPR2_FSMC_NADV
+.. doxygendefine:: AFIO_MAPR2_TIM14_REMAP
+.. doxygendefine:: AFIO_MAPR2_TIM13_REMAP
+.. doxygendefine:: AFIO_MAPR2_TIM11_REMAP
+.. doxygendefine:: AFIO_MAPR2_TIM10_REMAP
+.. doxygendefine:: AFIO_MAPR2_TIM9_REMAP
diff --git a/docs/source/libmaple/api/i2c.rst b/docs/source/libmaple/api/i2c.rst
new file mode 100644
index 0000000..ff380cc
--- /dev/null
+++ b/docs/source/libmaple/api/i2c.rst
@@ -0,0 +1,124 @@
+.. highlight:: c
+.. _libmaple-i2c:
+
+``i2c.h``
+=========
+
+Inter-Integrated Circuit (|i2c|) peripheral support.
+
+.. contents:: Contents
+ :local:
+
+Important Note
+--------------
+
+There are some important known problems with the built-in I2C
+peripherals. For more information, see STM32F10xx8 and STM32F10xxB
+Errata sheet (ST Doc ID 14574 Rev 8), Section 2.11.1, 2.11.2. An
+important consequence of these problems is that the |i2c| interrupt
+must not be preempted. Consequently, (by default) Wirish uses an
+|i2c| interrupt priority which is the highest in the system (priority
+level 0). Other interrupt priorities are set lower.
+
+Types
+-----
+
+.. doxygenstruct:: i2c_reg_map
+.. doxygenenum:: i2c_state
+.. doxygenstruct:: i2c_msg
+.. doxygenstruct:: i2c_dev
+
+Devices
+-------
+
+.. doxygenvariable:: I2C1
+.. doxygenvariable:: I2C2
+
+Functions
+---------
+
+.. doxygenfunction:: i2c_init
+.. doxygenfunction:: i2c_master_enable
+.. doxygenfunction:: i2c_master_xfer
+.. doxygenfunction:: i2c_bus_reset
+.. doxygenfunction:: i2c_disable
+.. doxygenfunction:: i2c_peripheral_enable
+.. doxygenfunction:: i2c_peripheral_disable
+.. doxygenfunction:: i2c_write
+.. doxygenfunction:: i2c_set_input_clk
+.. doxygenfunction:: i2c_set_clk_control
+.. doxygenfunction:: i2c_set_trise
+.. doxygenfunction:: i2c_start_condition
+.. doxygenfunction:: i2c_stop_condition
+.. doxygenfunction:: i2c_enable_irq
+.. doxygenfunction:: i2c_disable_irq
+.. doxygenfunction:: i2c_enable_ack
+.. doxygenfunction:: i2c_disable_ack
+
+Register Map Base Pointers
+--------------------------
+
+.. doxygendefine:: I2C1_BASE
+.. doxygendefine:: I2C2_BASE
+
+Register Bit Definitions
+------------------------
+
+Control register 1
+~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: I2C_CR1_SWRST
+.. doxygendefine:: I2C_CR1_ALERT
+.. doxygendefine:: I2C_CR1_PEC
+.. doxygendefine:: I2C_CR1_POS
+.. doxygendefine:: I2C_CR1_ACK
+.. doxygendefine:: I2C_CR1_START
+.. doxygendefine:: I2C_CR1_STOP
+.. doxygendefine:: I2C_CR1_PE
+
+Control register 2
+~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: I2C_CR2_LAST
+.. doxygendefine:: I2C_CR2_DMAEN
+.. doxygendefine:: I2C_CR2_ITBUFEN
+.. doxygendefine:: I2C_CR2_ITEVTEN
+.. doxygendefine:: I2C_CR2_ITERREN
+.. doxygendefine:: I2C_CR2_FREQ
+
+Clock control register
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: I2C_CCR_FS
+.. doxygendefine:: I2C_CCR_DUTY
+.. doxygendefine:: I2C_CCR_CCR
+
+Status register 1
+~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: I2C_SR1_SB
+.. doxygendefine:: I2C_SR1_ADDR
+.. doxygendefine:: I2C_SR1_BTF
+.. doxygendefine:: I2C_SR1_ADD10
+.. doxygendefine:: I2C_SR1_STOPF
+.. doxygendefine:: I2C_SR1_RXNE
+.. doxygendefine:: I2C_SR1_TXE
+.. doxygendefine:: I2C_SR1_BERR
+.. doxygendefine:: I2C_SR1_ARLO
+.. doxygendefine:: I2C_SR1_AF
+.. doxygendefine:: I2C_SR1_OVR
+.. doxygendefine:: I2C_SR1_PECERR
+.. doxygendefine:: I2C_SR1_TIMEOUT
+.. doxygendefine:: I2C_SR1_SMBALERT
+
+Status register 2
+~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: I2C_SR2_MSL
+.. doxygendefine:: I2C_SR2_BUSY
+.. doxygendefine:: I2C_SR2_TRA
+.. doxygendefine:: I2C_SR2_GENCALL
+.. doxygendefine:: I2C_SR2_SMBDEFAULT
+.. doxygendefine:: I2C_SR2_SMBHOST
+.. doxygendefine:: I2C_SR2_DUALF
+.. doxygendefine:: I2C_SR2_PEC
diff --git a/docs/source/libmaple/api/iwdg.rst b/docs/source/libmaple/api/iwdg.rst
new file mode 100644
index 0000000..65f9f7b
--- /dev/null
+++ b/docs/source/libmaple/api/iwdg.rst
@@ -0,0 +1,80 @@
+.. highlight:: c
+.. _libmaple-iwdg:
+
+``<libmaple/iwdg.h>``
+=====================
+
+Independent Watchdog (IWDG) support. The IWDG peripheral is common
+across supported targets, so everything documented here is portable.
+
+.. contents:: Contents
+ :local:
+
+Usage Note
+----------
+
+To use the independent watchdog, first call :ref:`iwdg_init()
+<libmaple-iwdg-iwdg_init>` with the appropriate prescaler and IWDG
+counter reload values for your application. Afterwards, you must
+periodically call :ref:`iwdg_feed() <libmaple-iwdg-iwdg_feed>` before
+the IWDG counter reaches zero to reset the counter to its reload
+value. If you do not, the chip will reset.
+
+Once started, the independent watchdog cannot be turned off.
+
+Devices
+-------
+
+None at this time.
+
+Functions
+---------
+
+.. _libmaple-iwdg-iwdg_init:
+.. doxygenfunction:: iwdg_init
+.. _libmaple-iwdg-iwdg_feed:
+.. doxygenfunction:: iwdg_feed
+
+Types
+-----
+
+.. doxygenenum:: iwdg_prescaler
+
+
+Register Maps
+-------------
+
+.. doxygendefine:: IWDG_BASE
+
+.. doxygenstruct:: iwdg_reg_map
+
+Register Bit Definitions
+------------------------
+
+These are given as source code.
+
+::
+
+ /* Key register */
+
+ #define IWDG_KR_UNLOCK 0x5555
+ #define IWDG_KR_FEED 0xAAAA
+ #define IWDG_KR_START 0xCCCC
+
+ /* Prescaler register */
+
+ #define IWDG_PR_DIV_4 0x0
+ #define IWDG_PR_DIV_8 0x1
+ #define IWDG_PR_DIV_16 0x2
+ #define IWDG_PR_DIV_32 0x3
+ #define IWDG_PR_DIV_64 0x4
+ #define IWDG_PR_DIV_128 0x5
+ #define IWDG_PR_DIV_256 0x6
+
+ /* Status register */
+
+ #define IWDG_SR_RVU_BIT 1
+ #define IWDG_SR_PVU_BIT 0
+
+ #define IWDG_SR_RVU (1U << IWDG_SR_RVU_BIT)
+ #define IWDG_SR_PVU (1U << IWDG_SR_PVU_BIT)
diff --git a/docs/source/libmaple/api/libmaple.rst b/docs/source/libmaple/api/libmaple.rst
new file mode 100644
index 0000000..7deb659
--- /dev/null
+++ b/docs/source/libmaple/api/libmaple.rst
@@ -0,0 +1,11 @@
+.. highlight:: c
+.. _libmaple-libmaple:
+
+``<libmaple/libmaple.h>``
+=========================
+
+Base include file for libmaple.
+
+This file includes :ref:`libmaple-libmaple_types`,
+:ref:`libmaple-stm32`, and :ref:`libmaple-util`. You shouldn't rely
+on it doing anything else, however.
diff --git a/docs/source/libmaple/api/libmaple_types.rst b/docs/source/libmaple/api/libmaple_types.rst
new file mode 100644
index 0000000..5ca446e
--- /dev/null
+++ b/docs/source/libmaple/api/libmaple_types.rst
@@ -0,0 +1,85 @@
+.. highlight:: c
+.. _libmaple-libmaple_types:
+
+``<libmaple/libmaple_types.h>``
+===============================
+
+Defines the base types and type-related macros used throughout the
+rest of libmaple.
+
+.. contents:: Contents
+ :local:
+
+Integral Types
+--------------
+
+.. doxygentypedef:: uint8
+.. doxygentypedef:: uint16
+.. doxygentypedef:: uint32
+.. doxygentypedef:: uint64
+.. doxygentypedef:: int8
+.. doxygentypedef:: int16
+.. doxygentypedef:: int32
+.. doxygentypedef:: int64
+
+Attributes and Type Qualifiers
+------------------------------
+
+In the case of macros for GCC's ``__attribute__``\ s, we have our own
+macros mostly to save typing, but also in hopes that they might be
+expressible using different compiler extensions, or to give them
+different interpretations when running e.g. Doxygen on libmaple.
+
+.. c:macro:: __always_inline
+
+ Macro for ``inline __attribute__((always_inline))``. This can be
+ used to defeat GCC's ``-Os`` when you Really Mean Inline.
+
+.. c:macro:: __attr_flash
+
+ Macro for a GCC ``__attribute__`` which (when using libmaple's
+ linker scripts) will cause the variable being marked to be stored
+ in Flash, rather than SRAM. It's useful for read-only variables
+ like look-up tables.
+
+.. c:macro:: __deprecated
+
+ Macro for ``__attribute__((deprecated))``. Its use causes GCC to
+ emit deprecation warnings when the deprecated functionality is
+ used. It's not used for everything that gets deprecated, so don't
+ rely on it to catch all uses of deprecated APIs.
+
+.. c:macro:: __packed
+
+ Macro for ``__attribute__((packed))``.
+
+.. c:macro:: __io
+
+ Macro for ``volatile`` which denotes that the variable whose type
+ is being qualified is IO-mapped. Its most common use is in the
+ individual members of each :ref:`register map
+ <libmaple-overview-regmaps>` struct.
+
+.. c:macro:: __weak
+
+ Macro for ``__attribute__((weak))``.
+
+.. c:macro:: __unused
+
+ Macro for ``__attribute__((unused))``. This can be used
+ (sparingly!) to silence unused function warnings when GCC is
+ mistaken.
+
+Miscellaneous
+-------------
+
+.. doxygentypedef:: voidFuncPtr
+
+.. c:macro:: offsetof(type, member)
+
+ If left undefined, this is defined to ``__builtin_ofsetof(type,
+ member)``.
+
+.. c:macro:: NULL
+
+ If left undefined, this is defined to ``0``.
diff --git a/docs/source/libmaple/api/nvic.rst b/docs/source/libmaple/api/nvic.rst
new file mode 100644
index 0000000..505e36e
--- /dev/null
+++ b/docs/source/libmaple/api/nvic.rst
@@ -0,0 +1,67 @@
+.. highlight:: c
+.. _libmaple-nvic:
+
+``<libmaple/nvic.h>``
+=====================
+
+Nested Vector Interrupt Controller (NVIC) support.
+
+The same API is used on all targets, but the available interrupts are
+target-dependent. To manage this, each target series defines an
+:ref:`nvic_irq_num <libmaple-nvic-nvic_irq_num>` enumerator for each
+available interrupt.
+
+.. contents:: Contents
+ :local:
+
+Devices
+-------
+
+None at this time.
+
+.. _libmaple-nvic-nvic_irq_num:
+
+``nvic_irq_num``
+----------------
+
+This target-dependent enum is used to identify an interrupt vector
+number. Interrupts which are common across series have the same token
+(though not necessarily the same value) for their ``nvic_irq_num``\ s.
+The available values on each supported target series are as follows.
+
+STM32F1 Targets
+~~~~~~~~~~~~~~~
+
+.. doxygenenum:: stm32f1::nvic_irq_num
+
+STM32F2 Targets
+~~~~~~~~~~~~~~~
+
+.. doxygenenum:: stm32f2::nvic_irq_num
+
+Functions
+---------
+
+.. doxygenfunction:: nvic_init
+.. doxygenfunction:: nvic_set_vector_table
+.. doxygenfunction:: nvic_irq_set_priority
+.. doxygenfunction:: nvic_globalirq_enable
+.. doxygenfunction:: nvic_globalirq_disable
+.. doxygenfunction:: nvic_irq_enable
+.. doxygenfunction:: nvic_irq_disable
+.. doxygenfunction:: nvic_irq_disable_all
+.. doxygenfunction:: nvic_sys_reset
+
+Register Maps
+-------------
+
+Since the NVIC is part of the ARM core, its registers and base pointer
+are common across all targes.
+
+.. doxygendefine:: NVIC_BASE
+.. doxygenstruct:: nvic_reg_map
+
+Register Bit Definitions
+------------------------
+
+None at this time.
diff --git a/docs/source/libmaple/api/pwr.rst b/docs/source/libmaple/api/pwr.rst
new file mode 100644
index 0000000..6a2cf22
--- /dev/null
+++ b/docs/source/libmaple/api/pwr.rst
@@ -0,0 +1,51 @@
+.. highlight:: c
+.. _libmaple-pwr:
+
+``pwr.h``
+=========
+
+Power control (PWR) support.
+
+.. contents:: Contents
+ :local:
+
+Types
+-----
+
+.. doxygenstruct:: pwr_reg_map
+
+Devices
+-------
+
+None.
+
+Functions
+---------
+
+.. doxygenfunction:: pwr_init
+
+Register Map Base Pointers
+--------------------------
+
+.. doxygendefine:: PWR_BASE
+
+Register Bit Definitions
+------------------------
+
+Control register
+~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: PWR_CR_DBP
+.. doxygendefine:: PWR_CR_PVDE
+.. doxygendefine:: PWR_CR_CSBF
+.. doxygendefine:: PWR_CR_CWUF
+.. doxygendefine:: PWR_CR_PDDS
+.. doxygendefine:: PWR_CR_LPDS
+
+Control and status register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: PWR_CSR_EWUP
+.. doxygendefine:: PWR_CSR_PVDO
+.. doxygendefine:: PWR_CSR_SBF
+.. doxygendefine:: PWR_CSR_WUF
diff --git a/docs/source/libmaple/api/rcc-reg-bits.txt b/docs/source/libmaple/api/rcc-reg-bits.txt
new file mode 100644
index 0000000..6b1133d
--- /dev/null
+++ b/docs/source/libmaple/api/rcc-reg-bits.txt
@@ -0,0 +1,1017 @@
+STM32F1 Targets
+~~~~~~~~~~~~~~~
+
+Clock control register
+++++++++++++++++++++++
+
+::
+
+ #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_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)
+
+Clock configuration register
+++++++++++++++++++++++++++++
+
+::
+
+ #define RCC_CFGR_USBPRE_BIT 22
+ #define RCC_CFGR_PLLXTPRE_BIT 17
+ #define RCC_CFGR_PLLSRC_BIT 16
+
+ #define RCC_CFGR_MCO (0x3 << 24)
+ #define RCC_CFGR_USBPRE (1U << RCC_CFGR_USBPRE_BIT)
+ #define RCC_CFGR_PLLMUL (0xF << 18)
+ #define RCC_CFGR_PLLXTPRE (1U << RCC_CFGR_PLLXTPRE_BIT)
+ #define RCC_CFGR_PLLSRC (1U << RCC_CFGR_PLLSRC_BIT)
+ #define RCC_CFGR_ADCPRE (0x3 << 14)
+ #define RCC_CFGR_PPRE2 (0x7 << 11)
+ #define RCC_CFGR_PPRE1 (0x7 << 8)
+ #define RCC_CFGR_HPRE (0xF << 4)
+ #define RCC_CFGR_SWS (0x3 << 2)
+ #define RCC_CFGR_SWS_PLL (0x2 << 2)
+ #define RCC_CFGR_SWS_HSE (0x1 << 2)
+ #define RCC_CFGR_SW 0x3
+ #define RCC_CFGR_SW_PLL 0x2
+ #define RCC_CFGR_SW_HSE 0x1
+
+Clock interrupt register
+++++++++++++++++++++++++
+
+::
+
+ #define RCC_CIR_CSSC_BIT 23
+ #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_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_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_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_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_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)
+
+Peripheral reset registers
+++++++++++++++++++++++++++
+
+::
+
+ #define RCC_APB2RSTR_TIM11RST_BIT 21
+ #define RCC_APB2RSTR_TIM10RST_BIT 20
+ #define RCC_APB2RSTR_TIM9RST_BIT 19
+ #define RCC_APB2RSTR_ADC3RST_BIT 15
+ #define RCC_APB2RSTR_USART1RST_BIT 14
+ #define RCC_APB2RSTR_TIM8RST_BIT 13
+ #define RCC_APB2RSTR_SPI1RST_BIT 12
+ #define RCC_APB2RSTR_TIM1RST_BIT 11
+ #define RCC_APB2RSTR_ADC2RST_BIT 10
+ #define RCC_APB2RSTR_ADC1RST_BIT 9
+ #define RCC_APB2RSTR_IOPGRST_BIT 8
+ #define RCC_APB2RSTR_IOPFRST_BIT 7
+ #define RCC_APB2RSTR_IOPERST_BIT 6
+ #define RCC_APB2RSTR_IOPDRST_BIT 5
+ #define RCC_APB2RSTR_IOPCRST_BIT 4
+ #define RCC_APB2RSTR_IOPBRST_BIT 3
+ #define RCC_APB2RSTR_IOPARST_BIT 2
+ #define RCC_APB2RSTR_AFIORST_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_ADC3RST (1U << RCC_APB2RSTR_ADC3RST_BIT)
+ #define RCC_APB2RSTR_USART1RST (1U << RCC_APB2RSTR_USART1RST_BIT)
+ #define RCC_APB2RSTR_TIM8RST (1U << RCC_APB2RSTR_TIM8RST_BIT)
+ #define RCC_APB2RSTR_SPI1RST (1U << RCC_APB2RSTR_SPI1RST_BIT)
+ #define RCC_APB2RSTR_TIM1RST (1U << RCC_APB2RSTR_TIM1RST_BIT)
+ #define RCC_APB2RSTR_ADC2RST (1U << RCC_APB2RSTR_ADC2RST_BIT)
+ #define RCC_APB2RSTR_ADC1RST (1U << RCC_APB2RSTR_ADC1RST_BIT)
+ #define RCC_APB2RSTR_IOPGRST (1U << RCC_APB2RSTR_IOPGRST_BIT)
+ #define RCC_APB2RSTR_IOPFRST (1U << RCC_APB2RSTR_IOPFRST_BIT)
+ #define RCC_APB2RSTR_IOPERST (1U << RCC_APB2RSTR_IOPERST_BIT)
+ #define RCC_APB2RSTR_IOPDRST (1U << RCC_APB2RSTR_IOPDRST_BIT)
+ #define RCC_APB2RSTR_IOPCRST (1U << RCC_APB2RSTR_IOPCRST_BIT)
+ #define RCC_APB2RSTR_IOPBRST (1U << RCC_APB2RSTR_IOPBRST_BIT)
+ #define RCC_APB2RSTR_IOPARST (1U << RCC_APB2RSTR_IOPARST_BIT)
+ #define RCC_APB2RSTR_AFIORST (1U << RCC_APB2RSTR_AFIORST_BIT)
+
+ #define RCC_APB1RSTR_DACRST_BIT 29
+ #define RCC_APB1RSTR_PWRRST_BIT 28
+ #define RCC_APB1RSTR_BKPRST_BIT 27
+ #define RCC_APB1RSTR_CANRST_BIT 25
+ #define RCC_APB1RSTR_USBRST_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_USART3RST_BIT 18
+ #define RCC_APB1RSTR_USART2RST_BIT 17
+ #define RCC_APB1RSTR_SPI3RST_BIT 15
+ #define RCC_APB1RSTR_SPI2RST_BIT 14
+ #define RCC_APB1RSTR_WWDRST_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_BKPRST (1U << RCC_APB1RSTR_BKPRST_BIT)
+ #define RCC_APB1RSTR_CANRST (1U << RCC_APB1RSTR_CANRST_BIT)
+ #define RCC_APB1RSTR_USBRST (1U << RCC_APB1RSTR_USBRST_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_USART3RST (1U << RCC_APB1RSTR_USART3RST_BIT)
+ #define RCC_APB1RSTR_USART2RST (1U << RCC_APB1RSTR_USART2RST_BIT)
+ #define RCC_APB1RSTR_SPI3RST (1U << RCC_APB1RSTR_SPI3RST_BIT)
+ #define RCC_APB1RSTR_SPI2RST (1U << RCC_APB1RSTR_SPI2RST_BIT)
+ #define RCC_APB1RSTR_WWDRST (1U << RCC_APB1RSTR_WWDRST_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)
+
+Peripheral clock enable registers
++++++++++++++++++++++++++++++++++
+
+::
+
+ #define RCC_AHBENR_SDIOEN_BIT 10
+ #define RCC_AHBENR_FSMCEN_BIT 8
+ #define RCC_AHBENR_CRCEN_BIT 7
+ #define RCC_AHBENR_FLITFEN_BIT 4
+ #define RCC_AHBENR_SRAMEN_BIT 2
+ #define RCC_AHBENR_DMA2EN_BIT 1
+ #define RCC_AHBENR_DMA1EN_BIT 0
+
+ #define RCC_AHBENR_SDIOEN (1U << RCC_AHBENR_SDIOEN_BIT)
+ #define RCC_AHBENR_FSMCEN (1U << RCC_AHBENR_FSMCEN_BIT)
+ #define RCC_AHBENR_CRCEN (1U << RCC_AHBENR_CRCEN_BIT)
+ #define RCC_AHBENR_FLITFEN (1U << RCC_AHBENR_FLITFEN_BIT)
+ #define RCC_AHBENR_SRAMEN (1U << RCC_AHBENR_SRAMEN_BIT)
+ #define RCC_AHBENR_DMA2EN (1U << RCC_AHBENR_DMA2EN_BIT)
+ #define RCC_AHBENR_DMA1EN (1U << RCC_AHBENR_DMA1EN_BIT)
+
+ #define RCC_APB2ENR_TIM11EN_BIT 21
+ #define RCC_APB2ENR_TIM10EN_BIT 20
+ #define RCC_APB2ENR_TIM9EN_BIT 19
+ #define RCC_APB2ENR_ADC3EN_BIT 15
+ #define RCC_APB2ENR_USART1EN_BIT 14
+ #define RCC_APB2ENR_TIM8EN_BIT 13
+ #define RCC_APB2ENR_SPI1EN_BIT 12
+ #define RCC_APB2ENR_TIM1EN_BIT 11
+ #define RCC_APB2ENR_ADC2EN_BIT 10
+ #define RCC_APB2ENR_ADC1EN_BIT 9
+ #define RCC_APB2ENR_IOPGEN_BIT 8
+ #define RCC_APB2ENR_IOPFEN_BIT 7
+ #define RCC_APB2ENR_IOPEEN_BIT 6
+ #define RCC_APB2ENR_IOPDEN_BIT 5
+ #define RCC_APB2ENR_IOPCEN_BIT 4
+ #define RCC_APB2ENR_IOPBEN_BIT 3
+ #define RCC_APB2ENR_IOPAEN_BIT 2
+ #define RCC_APB2ENR_AFIOEN_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_ADC3EN (1U << RCC_APB2ENR_ADC3EN_BIT)
+ #define RCC_APB2ENR_USART1EN (1U << RCC_APB2ENR_USART1EN_BIT)
+ #define RCC_APB2ENR_TIM8EN (1U << RCC_APB2ENR_TIM8EN_BIT)
+ #define RCC_APB2ENR_SPI1EN (1U << RCC_APB2ENR_SPI1EN_BIT)
+ #define RCC_APB2ENR_TIM1EN (1U << RCC_APB2ENR_TIM1EN_BIT)
+ #define RCC_APB2ENR_ADC2EN (1U << RCC_APB2ENR_ADC2EN_BIT)
+ #define RCC_APB2ENR_ADC1EN (1U << RCC_APB2ENR_ADC1EN_BIT)
+ #define RCC_APB2ENR_IOPGEN (1U << RCC_APB2ENR_IOPGEN_BIT)
+ #define RCC_APB2ENR_IOPFEN (1U << RCC_APB2ENR_IOPFEN_BIT)
+ #define RCC_APB2ENR_IOPEEN (1U << RCC_APB2ENR_IOPEEN_BIT)
+ #define RCC_APB2ENR_IOPDEN (1U << RCC_APB2ENR_IOPDEN_BIT)
+ #define RCC_APB2ENR_IOPCEN (1U << RCC_APB2ENR_IOPCEN_BIT)
+ #define RCC_APB2ENR_IOPBEN (1U << RCC_APB2ENR_IOPBEN_BIT)
+ #define RCC_APB2ENR_IOPAEN (1U << RCC_APB2ENR_IOPAEN_BIT)
+ #define RCC_APB2ENR_AFIOEN (1U << RCC_APB2ENR_AFIOEN_BIT)
+
+ #define RCC_APB1ENR_DACEN_BIT 29
+ #define RCC_APB1ENR_PWREN_BIT 28
+ #define RCC_APB1ENR_BKPEN_BIT 27
+ #define RCC_APB1ENR_CANEN_BIT 25
+ #define RCC_APB1ENR_USBEN_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_WWDEN_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_BKPEN (1U << RCC_APB1ENR_BKPEN_BIT)
+ #define RCC_APB1ENR_CANEN (1U << RCC_APB1ENR_CANEN_BIT)
+ #define RCC_APB1ENR_USBEN (1U << RCC_APB1ENR_USBEN_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_WWDEN (1U << RCC_APB1ENR_WWDEN_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)
+
+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_RTC_BIT)
+ #define RCC_BDCR_RTCSEL (0x3 << 8)
+ #define RCC_BDCR_RTCSEL_NONE (0x0 << 8)
+ #define RCC_BDCR_RTCSEL_LSE (0x1 << 8)
+ #define RCC_BDCR_RTCSEL_HSE (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)
+
+Control/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_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_RMVF (1U << RCC_CSR_RMVF_BIT)
+ #define RCC_CSR_LSIRDY (1U << RCC_CSR_LSIRDY_BIT)
+ #define RCC_CSR_LSION (1U << RCC_CSR_LSION_BIT)
+
+STM32F2 Targets
+~~~~~~~~~~~~~~~
+
+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)
+ #define RCC_PLLCFGR_PLLM 0x1F
+
+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)
+
+Peripheral reset registers
+++++++++++++++++++++++++++
+
+::
+
+ /* AHB1 */
+
+ #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 */
+
+ #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 */
+
+ #define RCC_AHB3RSTR_FSMCRST_BIT 0
+
+ #define RCC_AHB3RSTR_FSMCRST (1U << RCC_AHB3RSTR_FSMCRST_BIT)
+
+ /* APB1 */
+
+ #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 */
+
+ #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)
+
+Peripheral clock enable registers
++++++++++++++++++++++++++++++++++
+
+::
+
+ /* AHB1 */
+
+ #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 */
+
+ #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 */
+
+ #define RCC_AHB3ENR_FSMCEN_BIT 0
+
+ #define RCC_AHB3ENR_FSMCEN (1U << RCC_AHB3ENR_FSMCEN_BIT)
+
+ /* APB1 */
+
+ #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 */
+
+ #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)
+
+Peripheral clock enable in low power mode registers
++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+::
+
+ /* AHB1 */
+
+ #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 */
+
+ #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 */
+
+ #define RCC_AHB3LPENR_FSMCLPEN_BIT 0
+
+ #define RCC_AHB3LPENR_FSMCLPEN (1U << RCC_AHB3LPENR_FSMCLPEN_BIT)
+
+ /* APB1 */
+
+ #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 */
+
+ #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)
+
diff --git a/docs/source/libmaple/api/rcc.rst b/docs/source/libmaple/api/rcc.rst
new file mode 100644
index 0000000..ce58ec8
--- /dev/null
+++ b/docs/source/libmaple/api/rcc.rst
@@ -0,0 +1,360 @@
+.. highlight:: c
+.. _libmaple-rcc:
+
+``<libmaple/rcc.h>``
+====================
+
+Reset and Clock Control (RCC) support.
+
+The RCC is responsible for managing the MCU's various clocks. This
+includes the core clock SYSCLK, which determines the CPU clock
+frequency, as well as the clock lines that drive peripherals.
+
+Because of this, the available RCC functionality varies by target.
+There are a :ref:`variety of abstractions <libmaple-rcc-core-types>`
+in place to make managing this more convenient.
+
+.. contents:: Contents
+ :local:
+ :depth: 2
+
+.. _libmaple-rcc-core-types:
+
+Core Types
+----------
+
+The core abstractions in place are
+:ref:`rcc_clk_id <libmaple-rcc-rcc_clk_id>`,
+:ref:`rcc_clk <libmaple-rcc-rcc_clk>`,
+:ref:`rcc_sysclk_src <libmaple-rcc-rcc_sysclk_src>`,
+:ref:`rcc_clk_domain <libmaple-rcc-rcc_clk_domain>`, and
+:ref:`rcc_prescaler <libmaple-rcc-rcc_prescaler>`.
+
+.. _libmaple-rcc-rcc_clk_id:
+
+Peripheral Identifiers: ``rcc_clk_id``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``rcc_clk_id`` is an enum used to identify peripherals. The RCC
+back-ends use them to look up a peripheral's bus and clock line, but
+they are also generally useful as unique identifiers for each
+peripheral. You can manage peripherals using their ``rcc_clk_id``\ s
+with :ref:`these functions <libmaple-rcc-clk-id-funcs>`.
+
+Peripherals which are common across targets have the same token
+(though not necessarily the same value) for their ``rcc_clk_id``
+across different targets. For example, the ``rcc_clk_id`` for the ADC1
+peripheral is always ``RCC_ADC1`` regardless of the target.
+Additionally, as explained in :ref:`libmaple-overview-devices`, each
+peripheral device type struct contains the ``rcc_clk_id`` for that
+peripheral in a ``clk_id`` field.
+
+The available ``rcc_clk_id``\ s on each supported target series are as
+follows.
+
+STM32F1 Targets
++++++++++++++++
+
+.. doxygenenum:: stm32f1::rcc_clk_id
+
+STM32F2 Targets
++++++++++++++++
+
+.. doxygenenum:: stm32f2::rcc_clk_id
+
+.. _libmaple-rcc-rcc_sysclk_src:
+
+System Clock (SYSCLK) Sources: ``rcc_sysclk_src``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+SYSCLK is the core system clock. It determines the CPU clock rate, and
+it's the base clock which is used to drive (most of) the peripherals
+on the STM32. ``rcc_sysclk_src`` is an enum for the possible SYSCLK
+sources. Switch the SYSCLK source with :ref:`rcc_switch_sysclk()
+<libmaple-rcc-rcc_switch_sysclk>`.
+
+.. doxygenenum:: rcc_sysclk_src
+
+As a special case, you can configure the PLL with a call to
+:ref:`rcc_configure_pll() <libmaple-rcc-rcc_configure_pll>`.
+
+.. _libmaple-rcc-rcc_clk:
+
+System and Secondary Clock Sources: ``rcc_clk``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``rcc_clk`` type gives available system and secondary clock
+sources (e.g. HSI, HSE, LSE). As with :ref:`rcc_clk_id
+<libmaple-rcc-rcc_clk_id>`, clock sources which are common across
+targets have the same token, but not necessarily the same value, for
+their ``rcc_clk`` on each target. A variety of :ref:`clock management
+functions <libmaple-rcc-clk-funcs>` are available.
+
+Note that the inclusion of secondary clock sources, like LSI and LSE,
+makes ``rcc_clk`` different from the SYSCLK sources, which are managed
+using :ref:`rcc_sysclk_src <libmaple-rcc-rcc_sysclk_src>`.
+
+The available ``rcc_clk``\ s for each supported target series are as
+follows.
+
+STM32F1 Targets
++++++++++++++++
+
+.. doxygenenum:: stm32f1::rcc_clk
+
+STM32F2 Targets
++++++++++++++++
+
+.. doxygenenum:: stm32f2::rcc_clk
+
+.. _libmaple-rcc-rcc_clk_domain:
+
+Clock Domains: ``rcc_clk_domain``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These specify the available clock domains. For example, each AHB and
+APB is a clock domain.
+
+This type mostly exists to enable asking devices what bus they're on,
+which, given knowledge of your system's clock configuration, can be
+useful when making decisions about prescalers, etc.
+
+Given an :ref:`rcc_clk_id <libmaple-rcc-rcc_clk_id>`, you can get the
+peripheral's clock domain with :ref:`rcc_dev_clk()
+<libmaple-rcc-rcc_dev_clk>`. Clock domains that are common across
+series have the same token (but not necessarily the same value) for
+their corresponding ``rcc_clk_domain``.
+
+The available ``rcc_clk_domain``\ s for each supported target series
+are as follows.
+
+STM32F1 Targets
++++++++++++++++
+
+.. doxygenenum:: stm32f1::rcc_clk_domain
+
+STM32F2 Targets
++++++++++++++++
+
+.. doxygenenum:: stm32f2::rcc_clk_domain
+
+.. _libmaple-rcc-rcc_prescaler:
+
+Prescalers: ``rcc_prescaler`` and Friends
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Available prescalers are managed via the ``rcc_prescaler`` type, the
+``rcc_set_prescaler()`` function, and a variety of related prescaler
+divider types. See :ref:`libmaple-rcc-prescalers` for more
+information and usage notes.
+
+Functions
+---------
+
+.. _libmaple-rcc-sysclk-funcs:
+.. _libmaple-rcc-rcc_switch_sysclk:
+
+SYSCLK Management
+~~~~~~~~~~~~~~~~~
+
+Change the SYSCLK source with ``rcc_switch_sysclk()``.
+
+.. doxygenfunction:: rcc_switch_sysclk
+
+.. _libmaple-rcc-rcc_configure_pll:
+
+PLL Configuration
+~~~~~~~~~~~~~~~~~
+
+You can configure the PLL with ``rcc_configure_pll()``. This takes an
+``rcc_pll_cfg`` struct as its argument. Though the definition of
+``rcc_pll_cfg`` is common across series, its contents are entirely
+target-dependent.
+
+.. doxygenstruct:: rcc_pll_cfg
+.. _rcc-rcc_configure_pll:
+.. doxygenfunction:: rcc_configure_pll
+
+The fields in an ``rcc_pll_cfg`` on each target are as follows.
+
+rcc_pll_cfg on STM32F1 Targets
+++++++++++++++++++++++++++++++
+
+The ``pllsrc`` field is chosen from the following.
+
+.. doxygenenum:: stm32f1::rcc_pllsrc
+
+.. FIXME [0.0.13] We've got plans to redo this; make sure you watch
+.. libmaple for changes here.
+
+The ``data`` field must point to a ``struct stm32f1_rcc_pll_data``.
+This just contains an ``rcc_pll_multiplier``.
+
+.. doxygenenum:: stm32f1::rcc_pll_multiplier
+
+.. doxygenstruct:: stm32f1::stm32f1_rcc_pll_data
+
+rcc_pll_cfg on STM32F2 Targets
+++++++++++++++++++++++++++++++
+
+The ``pllsrc`` field is chosen from the following.
+
+.. doxygenenum:: stm32f2::rcc_pllsrc
+
+The ``data`` field must point to a ``struct stm32f2_rcc_pll_data``.
+
+.. doxygenstruct:: stm32f2::stm32f2_rcc_pll_data
+
+.. _libmaple-rcc-clk-funcs:
+
+System and Secondary Clock Management
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These functions are useful for managing clocks via their :ref:`rcc_clk
+<libmaple-rcc-rcc_clk>`.
+
+.. doxygenfunction:: rcc_turn_on_clk
+.. doxygenfunction:: rcc_turn_off_clk
+.. doxygenfunction:: rcc_is_clk_on
+.. doxygenfunction:: rcc_is_clk_ready
+
+.. _libmaple-rcc-clk-id-funcs:
+
+Peripheral Management
+~~~~~~~~~~~~~~~~~~~~~
+
+These functions are useful for managing peripherals via their
+:ref:`rcc_clk_id <libmaple-rcc-rcc_clk_id>`.
+
+.. _libmaple-rcc-rcc_clk_enable:
+.. doxygenfunction:: rcc_clk_enable
+.. doxygenfunction:: rcc_reset_dev
+.. _libmaple-rcc-rcc_dev_clk:
+.. doxygenfunction:: rcc_dev_clk
+
+.. _libmaple-rcc-prescalers:
+
+Prescaler Management
+~~~~~~~~~~~~~~~~~~~~
+
+All clock prescalers managed by RCC can be controlled with a single
+function, ``rcc_set_prescaler()``.
+
+.. doxygenfunction:: rcc_set_prescaler
+
+The arguments to ``rcc_set_prescaler()`` are target-dependent, but
+follow a common pattern:
+
+- The first argument is the prescaler to set, so there's one for each
+ peripheral clock domain, etc. These have names like
+ ``RCC_PRESCALER_FOO``, e.g. ``RCC_PRESCALER_APB1``. Choose the
+ prescaler from the ``rcc_prescaler``\ s on your target (see below).
+
+- The second argument is the actual clock divider to use; it's chosen
+ based on the first argument. The dividers for ``RCC_PRESCALER_FOO``
+ are given by the type ``rcc_foo_divider``, and have values like
+ ``RCC_FOO_xxx_DIV_y``. This means that the foo clock will be the
+ ``xxx`` clock divided by ``y``.
+
+For example, calling ``rcc_set_prescaler(RCC_PRESCALER_APB1,
+RCC_APB1_HCLK_DIV_1)`` would set the APB1 clock to HCLK divided by 1.
+
+Prescalers which are common across targets have the same token, though
+not necessarily the same value, for their ``rcc_prescaler`` (for
+example, ``RCC_PRESCALER_APB1`` is available on both STM32F1 and
+STM32F2 targets). The available prescalers and dividers on each
+supported target series are as follows.
+
+STM32F1 Targets
++++++++++++++++
+
+.. doxygenenum:: stm32f1::rcc_prescaler
+.. doxygenenum:: stm32f1::rcc_adc_divider
+.. doxygenenum:: stm32f1::rcc_apb1_divider
+.. doxygenenum:: stm32f1::rcc_apb2_divider
+.. doxygenenum:: stm32f1::rcc_ahb_divider
+
+STM32F2 Targets
++++++++++++++++
+
+.. doxygenenum:: stm32f2::rcc_prescaler
+.. doxygenenum:: stm32f2::rcc_mco2_divider
+.. doxygenenum:: stm32f2::rcc_mco1_divider
+.. doxygenenum:: stm32f2::rcc_rtc_divider
+.. doxygenenum:: stm32f2::rcc_apb2_divider
+.. doxygenenum:: stm32f2::rcc_apb1_divider
+.. doxygenenum:: stm32f2::rcc_ahb_divider
+
+Register Maps
+-------------
+
+These vary by target. The base pointer is always ``RCC_BASE``.
+
+.. doxygendefine:: RCC_BASE
+
+STM32F1 Targets
+~~~~~~~~~~~~~~~
+
+.. doxygenstruct:: stm32f1::rcc_reg_map
+
+STM32F2 Targets
+~~~~~~~~~~~~~~~
+
+.. doxygenstruct:: stm32f2::rcc_reg_map
+
+Register Bit Definitions
+------------------------
+
+These are given as source code. Available register bit definitions
+vary by target.
+
+.. We need this include to avoid crashing Emacs's ReST parser. Yuck.
+
+.. include:: rcc-reg-bits.txt
+
+Deprecated Functionality
+------------------------
+
+.. _rcc-rcc_clk_init:
+.. doxygenfunction:: stm32f1::rcc_clk_init
+
+To replace a call to ``rcc_clk_init()`` in order to set SYSCLK to PLL
+driven by an external oscillator, you can use something like this,
+which is portable except for the initialization of ``your_pll_cfg``::
+
+ /* You need to make this point to something valid for your target; see
+ * the documentation for rcc_configure_pll() for more details. */
+ extern rcc_pll_cfg *your_pll_cfg;
+
+ void pll_reconfigure() {
+ /* Turn on HSI using rcc_turn_on_clk() and wait for it to
+ * become ready by busy-waiting on rcc_is_clk_ready().
+ *
+ * Switch to HSI to ensure we're not using the PLL while we
+ * reconfigure it. */
+ rcc_turn_on_clk(RCC_CLK_HSI);
+ while (!rcc_is_clk_ready(RCC_CLK_HSI))
+ ;
+ rcc_switch_sysclk(RCC_CLKSRC_HSI);
+
+ /* Turn off HSE and the PLL, or we can't reconfigure it. */
+ rcc_turn_off_clk(RCC_CLK_PLL);
+ rcc_turn_off_clk(RCC_CLK_HSE);
+
+ /* Reconfigure the PLL. You can also perform any other
+ * prescaler management here. */
+ rcc_configure_pll(your_pll_cfg);
+
+ /* Turn on RCC_CLK_HSE. */
+ rcc_turn_on_clk(RCC_CLK_HSE);
+ while (!rcc_is_clk_ready(RCC_CLK_HSE))
+ ;
+
+ /* Turn on RCC_CLK_PLL. */
+ rcc_turn_on_clk(RCC_CLK_PLL);
+ while (!rcc_is_clk_ready(RCC_CLK_PLL))
+ ;
+
+ /* Finally, switch to the PLL. */
+ rcc_switch_sysclk(RCC_CLKSRC_PLL);
+ }
diff --git a/docs/source/libmaple/api/ring_buffer.rst b/docs/source/libmaple/api/ring_buffer.rst
new file mode 100644
index 0000000..ef082dd
--- /dev/null
+++ b/docs/source/libmaple/api/ring_buffer.rst
@@ -0,0 +1,27 @@
+.. highlight:: c
+.. _libmaple-ring_buffer:
+
+``<libmaple/ring_buffer.h>``
+============================
+
+Simple circular byte buffer. This implementation is not thread-safe.
+In particular, none of these functions is guaranteed to be re-entrant.
+
+Ring Buffer Type
+----------------
+
+.. doxygenstruct:: ring_buffer
+
+Ring Buffer Operations
+----------------------
+
+.. doxygenfunction:: rb_init
+.. doxygenfunction:: rb_full_count
+.. doxygenfunction:: rb_is_full
+.. doxygenfunction:: rb_is_empty
+.. doxygenfunction:: rb_insert
+.. doxygenfunction:: rb_remove
+.. doxygenfunction:: rb_safe_remove
+.. doxygenfunction:: rb_safe_insert
+.. doxygenfunction:: rb_push_insert
+.. doxygenfunction:: rb_reset
diff --git a/docs/source/libmaple/api/scb.rst b/docs/source/libmaple/api/scb.rst
new file mode 100644
index 0000000..96d464f
--- /dev/null
+++ b/docs/source/libmaple/api/scb.rst
@@ -0,0 +1,156 @@
+.. highlight:: c
+.. _libmaple-scb:
+
+``<libmaple/scb.h>``
+====================
+
+.. TODO [0.0.13] check for any F2 modifications
+
+System Control Block (SCB) support. This is currently limited to a
+register map and bit definitions.
+
+.. warning::
+
+ At time of writing, ST PM0056 (which specifies the system control
+ block on STM32F1) appears to be buggy (some registers required or
+ specified as implementation-defined by ARM are not mentioned).
+ This file is the result of combining material from ARM and ST, and
+ is subject to change. See the source code for more details.
+
+ If you notice a problem or have any other input on this, please
+ `contact`_ us!
+
+.. contents:: Contents
+ :local:
+
+Register Maps
+-------------
+
+The SCB has the following register map. Its base pointer is ``SCB_BASE``.
+
+.. doxygenstruct:: scb_reg_map
+.. doxygendefine:: SCB_BASE
+
+Register Bit Definitions
+------------------------
+
+These are given as source code.
+
+::
+
+ /* No SCB_REG_FIELD_BIT macros as the relevant addresses are not in a
+ * bit-band region. */
+
+ /* CPUID base register (SCB_CPUID) */
+
+ #define SCB_CPUID_IMPLEMENTER (0xFF << 24)
+ #define SCB_CPUID_VARIANT (0xF << 20)
+ #define SCB_CPUID_CONSTANT (0xF << 16)
+ #define SCB_CPUID_PARTNO (0xFFF << 4)
+ #define SCB_CPUID_REVISION 0xF
+
+ /* Interrupt control state register (SCB_ICSR) */
+
+ #define SCB_ICSR_NMIPENDSET (1U << 31)
+ #define SCB_ICSR_PENDSVSET (1U << 28)
+ #define SCB_ICSR_PENDSVCLR (1U << 27)
+ #define SCB_ICSR_PENDSTSET (1U << 26)
+ #define SCB_ICSR_PENDSTCLR (1U << 25)
+ #define SCB_ICSR_ISRPENDING (1U << 22)
+ #define SCB_ICSR_VECTPENDING (0x3FF << 12)
+ #define SCB_ICSR_RETOBASE (1U << 11)
+ #define SCB_ICSR_VECTACTIVE 0xFF
+
+ /* Vector table offset register (SCB_VTOR) */
+
+ #define SCB_VTOR_TBLOFF (0x1FFFFF << 9)
+
+ /* Application interrupt and reset control register (SCB_AIRCR) */
+
+ #define SCB_AIRCR_VECTKEYSTAT (0x5FA << 16)
+ #define SCB_AIRCR_VECTKEY (0x5FA << 16)
+ #define SCB_AIRCR_ENDIANNESS (1U << 15)
+ #define SCB_AIRCR_PRIGROUP (0x3 << 8)
+ #define SCB_AIRCR_SYSRESETREQ (1U << 2)
+ #define SCB_AIRCR_VECTCLRACTIVE (1U << 1)
+ #define SCB_AIRCR_VECTRESET (1U << 0)
+
+ /* System control register (SCB_SCR) */
+
+ #define SCB_SCR_SEVONPEND (1U << 4)
+ #define SCB_SCR_SLEEPDEEP (1U << 2)
+ #define SCB_SCR_SLEEPONEXIT (1U << 1)
+
+ /* Configuration and Control Register (SCB_CCR) */
+
+ #define SCB_CCR_STKALIGN (1U << 9)
+ #define SCB_CCR_BFHFNMIGN (1U << 8)
+ #define SCB_CCR_DIV_0_TRP (1U << 4)
+ #define SCB_CCR_UNALIGN_TRP (1U << 3)
+ #define SCB_CCR_USERSETMPEND (1U << 1)
+ #define SCB_CCR_NONBASETHRDENA (1U << 0)
+
+ /* System handler priority registers (SCB_SHPRx) */
+
+ #define SCB_SHPR1_PRI6 (0xFF << 16)
+ #define SCB_SHPR1_PRI5 (0xFF << 8)
+ #define SCB_SHPR1_PRI4 0xFF
+
+ #define SCB_SHPR2_PRI11 (0xFF << 24)
+
+ #define SCB_SHPR3_PRI15 (0xFF << 24)
+ #define SCB_SHPR3_PRI14 (0xFF << 16)
+
+ /* System Handler Control and state register (SCB_SHCSR) */
+
+ #define SCB_SHCSR_USGFAULTENA (1U << 18)
+ #define SCB_SHCSR_BUSFAULTENA (1U << 17)
+ #define SCB_SHCSR_MEMFAULTENA (1U << 16)
+ #define SCB_SHCSR_SVCALLPENDED (1U << 15)
+ #define SCB_SHCSR_BUSFAULTPENDED (1U << 14)
+ #define SCB_SHCSR_MEMFAULTPENDED (1U << 13)
+ #define SCB_SHCSR_USGFAULTPENDED (1U << 12)
+ #define SCB_SHCSR_SYSTICKACT (1U << 11)
+ #define SCB_SHCSR_PENDSVACT (1U << 10)
+ #define SCB_SHCSR_MONITORACT (1U << 8)
+ #define SCB_SHCSR_SVCALLACT (1U << 7)
+ #define SCB_SHCSR_USGFAULTACT (1U << 3)
+ #define SCB_SHCSR_BUSFAULTACT (1U << 1)
+ #define SCB_SHCSR_MEMFAULTACT (1U << 0)
+
+ /* Configurable fault status register (SCB_CFSR) */
+
+ #define SCB_CFSR_DIVBYZERO (1U << 25)
+ #define SCB_CFSR_UNALIGNED (1U << 24)
+ #define SCB_CFSR_NOCP (1U << 19)
+ #define SCB_CFSR_INVPC (1U << 18)
+ #define SCB_CFSR_INVSTATE (1U << 17)
+ #define SCB_CFSR_UNDEFINSTR (1U << 16)
+ #define SCB_CFSR_BFARVALID (1U << 15)
+ #define SCB_CFSR_STKERR (1U << 12)
+ #define SCB_CFSR_UNSTKERR (1U << 11)
+ #define SCB_CFSR_IMPRECISERR (1U << 10)
+ #define SCB_CFSR_PRECISERR (1U << 9)
+ #define SCB_CFSR_IBUSERR (1U << 8)
+ #define SCB_CFSR_MMARVALID (1U << 7)
+ #define SCB_CFSR_MSTKERR (1U << 4)
+ #define SCB_CFSR_MUNSTKERR (1U << 3)
+ #define SCB_CFSR_DACCVIOL (1U << 1)
+ #define SCB_CFSR_IACCVIOL (1U << 0)
+
+ /* Hard Fault Status Register (SCB_HFSR) */
+
+ #define SCB_HFSR_DEBUG_VT (1U << 31)
+ #define SCB_CFSR_FORCED (1U << 30)
+ #define SCB_CFSR_VECTTBL (1U << 1)
+
+ /* Debug Fault Status Register */
+
+ /* Not specified by PM0056, but required by ARM. The bit definitions
+ * here are based on the names given in the ARM v7-M ARM. */
+
+ #define SCB_DFSR_EXTERNAL (1U << 4)
+ #define SCB_DFSR_VCATCH (1U << 3)
+ #define SCB_DFSR_DWTTRAP (1U << 2)
+ #define SCB_DFSR_BKPT (1U << 1)
+ #define SCB_DFSR_HALTED (1U << 0)
diff --git a/docs/source/libmaple/api/spi.rst b/docs/source/libmaple/api/spi.rst
new file mode 100644
index 0000000..e72696b
--- /dev/null
+++ b/docs/source/libmaple/api/spi.rst
@@ -0,0 +1,187 @@
+.. highlight:: c
+.. _libmaple-spi:
+
+``spi.h``
+=========
+
+Serial Peripheral Interface (SPI) support. Currently, there is no I2S
+support beyond register bit definitions.
+
+.. contents:: Contents
+ :local:
+
+Types
+-----
+
+.. doxygenstruct:: spi_reg_map
+.. doxygenstruct:: spi_dev
+.. doxygenenum:: spi_mode
+.. doxygenenum:: spi_baud_rate
+.. doxygenenum:: spi_cfg_flag
+.. doxygenenum:: spi_interrupt
+
+Devices
+-------
+
+.. doxygenvariable:: SPI1
+.. doxygenvariable:: SPI2
+.. doxygenvariable:: SPI3
+
+Functions
+---------
+
+.. doxygenfunction:: spi_init
+.. doxygenfunction:: spi_gpio_cfg
+.. doxygenfunction:: spi_master_enable
+.. doxygenfunction:: spi_slave_enable
+.. doxygenfunction:: spi_tx
+.. doxygenfunction:: spi_foreach
+.. doxygenfunction:: spi_peripheral_enable
+.. doxygenfunction:: spi_peripheral_disable
+.. doxygenfunction:: spi_peripheral_disable_all
+.. doxygenfunction:: spi_tx_dma_enable
+.. doxygenfunction:: spi_tx_dma_disable
+.. doxygenfunction:: spi_rx_dma_enable
+.. doxygenfunction:: spi_rx_dma_disable
+.. doxygenfunction:: spi_is_enabled
+.. doxygenfunction:: spi_irq_enable
+.. doxygenfunction:: spi_irq_disable
+.. doxygenfunction:: spi_dff
+.. doxygenfunction:: spi_is_rx_nonempty
+.. doxygenfunction:: spi_rx_reg
+.. doxygenfunction:: spi_is_tx_empty
+.. doxygenfunction:: spi_tx_reg
+.. doxygenfunction:: spi_is_busy
+
+Register Map Base Pointers
+--------------------------
+
+.. doxygendefine:: SPI1_BASE
+.. doxygendefine:: SPI2_BASE
+.. doxygendefine:: SPI3_BASE
+
+Register Bit Definitions
+------------------------
+
+Control register 1
+~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: SPI_CR1_BIDIMODE_BIT
+.. doxygendefine:: SPI_CR1_BIDIOE_BIT
+.. doxygendefine:: SPI_CR1_CRCEN_BIT
+.. doxygendefine:: SPI_CR1_CRCNEXT_BIT
+.. doxygendefine:: SPI_CR1_DFF_BIT
+.. doxygendefine:: SPI_CR1_RXONLY_BIT
+.. doxygendefine:: SPI_CR1_SSM_BIT
+.. doxygendefine:: SPI_CR1_SSI_BIT
+.. doxygendefine:: SPI_CR1_LSBFIRST_BIT
+.. doxygendefine:: SPI_CR1_SPE_BIT
+.. doxygendefine:: SPI_CR1_MSTR_BIT
+.. doxygendefine:: SPI_CR1_CPOL_BIT
+.. doxygendefine:: SPI_CR1_CPHA_BIT
+
+.. doxygendefine:: SPI_CR1_BIDIMODE
+.. doxygendefine:: SPI_CR1_BIDIMODE_2_LINE
+.. doxygendefine:: SPI_CR1_BIDIMODE_1_LINE
+.. doxygendefine:: SPI_CR1_BIDIOE
+.. doxygendefine:: SPI_CR1_CRCEN
+.. doxygendefine:: SPI_CR1_CRCNEXT
+.. doxygendefine:: SPI_CR1_DFF
+.. doxygendefine:: SPI_CR1_DFF_8_BIT
+.. doxygendefine:: SPI_CR1_DFF_16_BIT
+.. doxygendefine:: SPI_CR1_RXONLY
+.. doxygendefine:: SPI_CR1_SSM
+.. doxygendefine:: SPI_CR1_SSI
+.. doxygendefine:: SPI_CR1_LSBFIRST
+.. doxygendefine:: SPI_CR1_SPE
+.. doxygendefine:: SPI_CR1_BR
+.. doxygendefine:: SPI_CR1_BR_PCLK_DIV_2
+.. doxygendefine:: SPI_CR1_BR_PCLK_DIV_4
+.. doxygendefine:: SPI_CR1_BR_PCLK_DIV_8
+.. doxygendefine:: SPI_CR1_BR_PCLK_DIV_16
+.. doxygendefine:: SPI_CR1_BR_PCLK_DIV_32
+.. doxygendefine:: SPI_CR1_BR_PCLK_DIV_64
+.. doxygendefine:: SPI_CR1_BR_PCLK_DIV_128
+.. doxygendefine:: SPI_CR1_BR_PCLK_DIV_256
+.. doxygendefine:: SPI_CR1_MSTR
+.. doxygendefine:: SPI_CR1_CPOL
+.. doxygendefine:: SPI_CR1_CPOL_LOW
+.. doxygendefine:: SPI_CR1_CPOL_HIGH
+.. doxygendefine:: SPI_CR1_CPHA
+
+Control register 2
+~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: SPI_CR2_TXEIE_BIT
+.. doxygendefine:: SPI_CR2_RXNEIE_BIT
+.. doxygendefine:: SPI_CR2_ERRIE_BIT
+.. doxygendefine:: SPI_CR2_SSOE_BIT
+.. doxygendefine:: SPI_CR2_TXDMAEN_BIT
+.. doxygendefine:: SPI_CR2_RXDMAEN_BIT
+
+.. doxygendefine:: SPI_CR2_TXEIE
+.. doxygendefine:: SPI_CR2_RXNEIE
+.. doxygendefine:: SPI_CR2_ERRIE
+.. doxygendefine:: SPI_CR2_SSOE
+.. doxygendefine:: SPI_CR2_TXDMAEN
+.. doxygendefine:: SPI_CR2_RXDMAEN
+
+Status register
+~~~~~~~~~~~~~~~
+
+.. doxygendefine:: SPI_SR_BSY_BIT
+.. doxygendefine:: SPI_SR_OVR_BIT
+.. doxygendefine:: SPI_SR_MODF_BIT
+.. doxygendefine:: SPI_SR_CRCERR_BIT
+.. doxygendefine:: SPI_SR_UDR_BIT
+.. doxygendefine:: SPI_SR_CHSIDE_BIT
+.. doxygendefine:: SPI_SR_TXE_BIT
+.. doxygendefine:: SPI_SR_RXNE_BIT
+
+.. doxygendefine:: SPI_SR_BSY
+.. doxygendefine:: SPI_SR_OVR
+.. doxygendefine:: SPI_SR_MODF
+.. doxygendefine:: SPI_SR_CRCERR
+.. doxygendefine:: SPI_SR_UDR
+.. doxygendefine:: SPI_SR_CHSIDE
+.. doxygendefine:: SPI_SR_CHSIDE_LEFT
+.. doxygendefine:: SPI_SR_CHSIDE_RIGHT
+.. doxygendefine:: SPI_SR_TXE
+.. doxygendefine:: SPI_SR_RXNE
+
+I2S configuration register
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: SPI_I2SCFGR_I2SMOD_BIT
+.. doxygendefine:: SPI_I2SCFGR_I2SE_BIT
+.. doxygendefine:: SPI_I2SCFGR_PCMSYNC_BIT
+.. doxygendefine:: SPI_I2SCFGR_CKPOL_BIT
+.. doxygendefine:: SPI_I2SCFGR_CHLEN_BIT
+
+.. doxygendefine:: SPI_I2SCFGR_I2SMOD
+.. doxygendefine:: SPI_I2SCFGR_I2SMOD_SPI
+.. doxygendefine:: SPI_I2SCFGR_I2SMOD_I2S
+.. doxygendefine:: SPI_I2SCFGR_I2SE
+.. doxygendefine:: SPI_I2SCFGR_I2SCFG
+.. doxygendefine:: SPI_I2SCFGR_I2SCFG_SLAVE_TX
+.. doxygendefine:: SPI_I2SCFGR_I2SCFG_SLAVE_RX
+.. doxygendefine:: SPI_I2SCFGR_I2SCFG_MASTER_TX
+.. doxygendefine:: SPI_I2SCFGR_I2SCFG_MASTER_RX
+.. doxygendefine:: SPI_I2SCFGR_PCMSYNC
+.. doxygendefine:: SPI_I2SCFGR_PCMSYNC_SHORT
+.. doxygendefine:: SPI_I2SCFGR_PCMSYNC_LONG
+.. doxygendefine:: SPI_I2SCFGR_I2SSTD
+.. doxygendefine:: SPI_I2SCFGR_I2SSTD_PHILLIPS
+.. doxygendefine:: SPI_I2SCFGR_I2SSTD_MSB
+.. doxygendefine:: SPI_I2SCFGR_I2SSTD_LSB
+.. doxygendefine:: SPI_I2SCFGR_I2SSTD_PCM
+.. doxygendefine:: SPI_I2SCFGR_CKPOL
+.. doxygendefine:: SPI_I2SCFGR_CKPOL_LOW
+.. doxygendefine:: SPI_I2SCFGR_CKPOL_HIGH
+.. doxygendefine:: SPI_I2SCFGR_DATLEN
+.. doxygendefine:: SPI_I2SCFGR_DATLEN_16_BIT
+.. doxygendefine:: SPI_I2SCFGR_DATLEN_24_BIT
+.. doxygendefine:: SPI_I2SCFGR_DATLEN_32_BIT
+.. doxygendefine:: SPI_I2SCFGR_CHLEN
+.. doxygendefine:: SPI_I2SCFGR_CHLEN_16_BIT
+.. doxygendefine:: SPI_I2SCFGR_CHLEN_32_BIT
diff --git a/docs/source/libmaple/api/stm32.rst b/docs/source/libmaple/api/stm32.rst
new file mode 100644
index 0000000..335bda4
--- /dev/null
+++ b/docs/source/libmaple/api/stm32.rst
@@ -0,0 +1,121 @@
+.. highlight:: c
+.. _libmaple-stm32:
+
+``<libmaple/stm32.h>``
+======================
+
+STM32 chip header. This header supplies various series-specific and
+chip-specific macros for the current build target. It's useful both
+to abstract away hardware details (e.g. through use of
+:ref:`STM32_NR_INTERRUPTS <libmaple-stm32-STM32_NR_INTERRUPTS>`) and
+to decide what to do when you want something nonportable (e.g. by
+checking :ref:`STM32_MCU_SERIES <libmaple-stm32-STM32_MCU_SERIES>`).
+
+.. contents:: Contents
+ :local:
+
+Determining the Target Series
+-----------------------------
+
+The STM32 series (e.g. STM32F1, STM32F2, etc.) of the current target
+can be inspected with ``STM32_MCU_SERIES``.
+
+.. _libmaple-stm32-STM32_MCU_SERIES:
+.. doxygendefine:: STM32_MCU_SERIES
+
+Allowed values for ``STM32_MCU_SERIES`` are the following. This set is
+expected to grow over time.
+
+.. doxygendefine:: STM32_SERIES_F1
+.. doxygendefine:: STM32_SERIES_F2
+.. doxygendefine:: STM32_SERIES_L1
+.. doxygendefine:: STM32_SERIES_F4
+
+Series-Specific Characteristics
+-------------------------------
+
+The macros in this section are only available on some STM32 series.
+
+STM32F1
+~~~~~~~
+
+.. note:: These macros are only available when the current target is
+ an STM32F1 series MCU (i.e., when :ref:`STM32_MCU_SERIES
+ <libmaple-stm32-STM32_MCU_SERIES>` is ``STM32_SERIES_F1``).
+
+The STM32F1 series is further subdivided into :ref:`lines
+<stm32-series-f1-lines>`. The line of the current target can be
+inspected with ``STM32_F1_LINE``.
+
+.. doxygendefine:: STM32_F1_LINE
+
+There are five STM32F1 lines. The corresponding values
+``STM32_F1_LINE`` can take are the following, though libmaple doesn't
+currently support all of them.
+
+.. doxygendefine:: STM32_F1_LINE_VALUE
+.. doxygendefine:: STM32_F1_LINE_ACCESS
+.. doxygendefine:: STM32_F1_LINE_USB_ACCESS
+.. doxygendefine:: STM32_F1_LINE_PERFORMANCE
+.. doxygendefine:: STM32_F1_LINE_CONNECTIVITY
+
+MCU Feature Tests
+-----------------
+
+The following defines can be used to determine if the target MCU has
+a particular feature.
+
+.. _libmaple-stm32-STM32_HAVE_FSMC:
+.. doxygendefine:: STM32_HAVE_FSMC
+.. doxygendefine:: STM32_HAVE_USB
+
+MCU Characteristics
+-------------------
+
+The following defines give salient characteristics of the target MCU.
+
+.. doxygendefine:: STM32_NR_GPIO_PORTS
+.. _libmaple-stm32-STM32_NR_INTERRUPTS:
+.. doxygendefine:: STM32_NR_INTERRUPTS
+.. doxygendefine:: STM32_SRAM_END
+
+Clock Speeds
+------------
+
+The macros in this section are related to clock rates. As such, they
+are really part of the configuration of the MCU, rather than inherent
+characteristics of the MCU itself. For instance, it's possible to
+change the PCLK1 and PCLK2 clock rates by reconfiguring the :ref:`RCC
+<libmaple-rcc>`. libmaple proper never changes any clock rates, but it
+does have APIs for doing so (such as :ref:`rcc_configure_pll()
+<libmaple-rcc-rcc_configure_pll>`). Because of this, be careful when
+using the macros in this section, as they assume that some values are
+constant which in fact may be changed.
+
+The values these macros actually take are typically the maximum values
+supported by the MCU. Since these are their actual values in practice
+(at least in LeafLabs' current use cases, which have the chips running
+as fast as possible), they're still considered useful.
+
+.. doxygendefine:: STM32_PCLK1
+.. doxygendefine:: STM32_PCLK2
+
+The following macro, ``STM32_DELAY_US_MULT``, is a libmaple
+implementation detail. It was included in this public API page in a
+previous release by mistake, and is not deprecated, but using it in
+your own code is a bad idea.
+
+.. doxygendefine:: STM32_DELAY_US_MULT
+
+Deprecated Macros
+-----------------
+
+.. warning:: The macros in this section are deprecated, and are
+ available for backwards compatibility only. Do not use
+ them in new code.
+
+.. doxygendefine:: PCLK1
+.. doxygendefine:: PCLK2
+.. doxygendefine:: NR_INTERRUPTS
+.. doxygendefine:: NR_GPIO_PORTS
+.. doxygendefine:: DELAY_US_MULT
diff --git a/docs/source/libmaple/api/systick.rst b/docs/source/libmaple/api/systick.rst
new file mode 100644
index 0000000..45b6d63
--- /dev/null
+++ b/docs/source/libmaple/api/systick.rst
@@ -0,0 +1,62 @@
+.. highlight:: c
+
+.. _libmaple-systick:
+
+``systick.h``
+=============
+
+System timer (SysTick) support.
+
+.. contents:: Contents
+ :local:
+
+Types
+-----
+
+.. doxygenstruct:: systick_reg_map
+
+Devices
+-------
+
+None.
+
+Functions
+---------
+
+.. doxygenfunction:: systick_init
+.. _libmaple-systick-enable:
+.. doxygenfunction:: systick_enable
+.. _libmaple-systick-disable:
+.. doxygenfunction:: systick_disable
+.. doxygenfunction:: systick_uptime
+.. doxygenfunction:: systick_get_count
+.. doxygenfunction:: systick_check_underflow
+
+Register Map Base Pointers
+--------------------------
+
+.. doxygendefine:: SYSTICK_BASE
+
+Register Bit Definitions
+------------------------
+
+Control and status register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: SYSTICK_CSR_COUNTFLAG
+.. doxygendefine:: SYSTICK_CSR_CLKSOURCE
+.. doxygendefine:: SYSTICK_CSR_CLKSOURCE_EXTERNAL
+.. doxygendefine:: SYSTICK_CSR_CLKSOURCE_CORE
+.. doxygendefine:: SYSTICK_CSR_TICKINT
+.. doxygendefine:: SYSTICK_CSR_TICKINT_PEND
+.. doxygendefine:: SYSTICK_CSR_TICKINT_NO_PEND
+.. doxygendefine:: SYSTICK_CSR_ENABLE
+.. doxygendefine:: SYSTICK_CSR_ENABLE_MULTISHOT
+.. doxygendefine:: SYSTICK_CSR_ENABLE_DISABLED
+
+Calibration value register
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: SYSTICK_CVR_NOREF
+.. doxygendefine:: SYSTICK_CVR_SKEW
+.. doxygendefine:: SYSTICK_CVR_TENMS
diff --git a/docs/source/libmaple/api/timer.rst b/docs/source/libmaple/api/timer.rst
new file mode 100644
index 0000000..f315cb0
--- /dev/null
+++ b/docs/source/libmaple/api/timer.rst
@@ -0,0 +1,453 @@
+.. highlight:: c
+.. _libmaple-timer:
+
+``timer.h``
+===========
+
+Timer support.
+
+.. contents:: Contents
+ :local:
+
+Types
+-----
+
+The timer register map type, unlike that for most other peripherals in
+libmaple, is a union rather than a struct. This is due to the fact
+that there are advanced, general purpose, and basic timers. Thus,
+each kind of timer has a register map type, and a ``union
+timer_reg_map`` ties it all together.
+
+.. doxygenstruct:: timer_adv_reg_map
+.. doxygenstruct:: timer_gen_reg_map
+.. doxygenstruct:: timer_bas_reg_map
+.. doxygenunion:: timer_reg_map
+.. doxygenenum:: timer_type
+.. doxygenstruct:: timer_dev
+.. doxygenenum:: timer_mode
+.. doxygenenum:: timer_channel
+.. doxygenenum:: timer_interrupt_id
+.. doxygenenum:: timer_dma_base_addr
+.. doxygenenum:: timer_oc_mode
+.. doxygenenum:: timer_oc_mode_flags
+
+Devices
+-------
+
+.. doxygenvariable:: TIMER1
+.. doxygenvariable:: TIMER2
+.. doxygenvariable:: TIMER3
+.. doxygenvariable:: TIMER4
+.. doxygenvariable:: TIMER5
+.. doxygenvariable:: TIMER6
+.. doxygenvariable:: TIMER7
+.. doxygenvariable:: TIMER8
+
+Functions
+---------
+
+Enabling and Disabling
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygenfunction:: timer_init
+.. doxygenfunction:: timer_init_all
+.. doxygenfunction:: timer_disable
+.. doxygenfunction:: timer_disable_all
+
+General Configuration
+~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygenfunction:: timer_set_mode
+.. doxygenfunction:: timer_foreach
+
+Count and Prescaler
+~~~~~~~~~~~~~~~~~~~
+
+.. doxygenfunction:: timer_get_count
+.. doxygenfunction:: timer_set_count
+.. doxygenfunction:: timer_pause
+.. doxygenfunction:: timer_resume
+.. doxygenfunction:: timer_generate_update
+.. doxygenfunction:: timer_get_prescaler
+.. doxygenfunction:: timer_set_prescaler
+.. doxygenfunction:: timer_get_reload
+.. doxygenfunction:: timer_set_reload
+
+Interrupts
+~~~~~~~~~~
+
+.. doxygenfunction:: timer_attach_interrupt
+.. doxygenfunction:: timer_detach_interrupt
+.. doxygenfunction:: timer_enable_irq
+.. doxygenfunction:: timer_disable_irq
+
+Capture/Compare
+~~~~~~~~~~~~~~~
+
+.. doxygenfunction:: timer_get_compare
+.. doxygenfunction:: timer_set_compare
+.. doxygenfunction:: timer_cc_enable
+.. doxygenfunction:: timer_cc_disable
+.. doxygenfunction:: timer_cc_get_pol
+.. doxygenfunction:: timer_cc_set_pol
+.. doxygenfunction:: timer_oc_set_mode
+
+DMA
+~~~
+
+.. doxygenfunction:: timer_dma_enable_trg_req
+.. doxygenfunction:: timer_dma_disable_trg_req
+.. doxygenfunction:: timer_dma_enable_req
+.. doxygenfunction:: timer_dma_get_burst_len
+.. doxygenfunction:: timer_dma_set_burst_len
+.. doxygenfunction:: timer_dma_get_base_addr
+.. doxygenfunction:: timer_dma_set_base_addr
+
+Register Map Base Pointers
+--------------------------
+
+.. doxygendefine:: TIMER1_BASE
+.. doxygendefine:: TIMER2_BASE
+.. doxygendefine:: TIMER3_BASE
+.. doxygendefine:: TIMER4_BASE
+.. doxygendefine:: TIMER5_BASE
+.. doxygendefine:: TIMER6_BASE
+.. doxygendefine:: TIMER7_BASE
+.. doxygendefine:: TIMER8_BASE
+
+Register Bit Definitions
+------------------------
+
+Control register 1 (CR1)
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: TIMER_CR1_ARPE_BIT
+.. doxygendefine:: TIMER_CR1_DIR_BIT
+.. doxygendefine:: TIMER_CR1_OPM_BIT
+.. doxygendefine:: TIMER_CR1_URS_BIT
+.. doxygendefine:: TIMER_CR1_UDIS_BIT
+.. doxygendefine:: TIMER_CR1_CEN_BIT
+
+.. doxygendefine:: TIMER_CR1_CKD
+.. doxygendefine:: TIMER_CR1_CKD_1TCKINT
+.. doxygendefine:: TIMER_CR1_CKD_2TCKINT
+.. doxygendefine:: TIMER_CR1_CKD_4TICKINT
+.. doxygendefine:: TIMER_CR1_ARPE
+.. doxygendefine:: TIMER_CR1_CKD_CMS
+.. doxygendefine:: TIMER_CR1_CKD_CMS_EDGE
+.. doxygendefine:: TIMER_CR1_CKD_CMS_CENTER1
+.. doxygendefine:: TIMER_CR1_CKD_CMS_CENTER2
+.. doxygendefine:: TIMER_CR1_CKD_CMS_CENTER3
+.. doxygendefine:: TIMER_CR1_DIR
+.. doxygendefine:: TIMER_CR1_OPM
+.. doxygendefine:: TIMER_CR1_URS
+.. doxygendefine:: TIMER_CR1_UDIS
+.. doxygendefine:: TIMER_CR1_CEN
+
+Control register 2 (CR2)
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: TIMER_CR2_OIS4_BIT
+.. doxygendefine:: TIMER_CR2_OIS3N_BIT
+.. doxygendefine:: TIMER_CR2_OIS3_BIT
+.. doxygendefine:: TIMER_CR2_OIS2N_BIT
+.. doxygendefine:: TIMER_CR2_OIS2_BIT
+.. doxygendefine:: TIMER_CR2_OIS1N_BIT
+.. doxygendefine:: TIMER_CR2_OIS1_BIT
+.. doxygendefine:: TIMER_CR2_TI1S_BIT
+.. doxygendefine:: TIMER_CR2_CCDS_BIT
+.. doxygendefine:: TIMER_CR2_CCUS_BIT
+.. doxygendefine:: TIMER_CR2_CCPC_BIT
+
+.. doxygendefine:: TIMER_CR2_OIS4
+.. doxygendefine:: TIMER_CR2_OIS3N
+.. doxygendefine:: TIMER_CR2_OIS3
+.. doxygendefine:: TIMER_CR2_OIS2N
+.. doxygendefine:: TIMER_CR2_OIS2
+.. doxygendefine:: TIMER_CR2_OIS1N
+.. doxygendefine:: TIMER_CR2_OIS1
+.. doxygendefine:: TIMER_CR2_TI1S
+.. doxygendefine:: TIMER_CR2_MMS
+.. doxygendefine:: TIMER_CR2_MMS_RESET
+.. doxygendefine:: TIMER_CR2_MMS_ENABLE
+.. doxygendefine:: TIMER_CR2_MMS_UPDATE
+.. doxygendefine:: TIMER_CR2_MMS_COMPARE_PULSE
+.. doxygendefine:: TIMER_CR2_MMS_COMPARE_OC1REF
+.. doxygendefine:: TIMER_CR2_MMS_COMPARE_OC2REF
+.. doxygendefine:: TIMER_CR2_MMS_COMPARE_OC3REF
+.. doxygendefine:: TIMER_CR2_MMS_COMPARE_OC4REF
+.. doxygendefine:: TIMER_CR2_CCDS
+.. doxygendefine:: TIMER_CR2_CCUS
+.. doxygendefine:: TIMER_CR2_CCPC
+
+Slave mode control register (SMCR)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: TIMER_SMCR_ETP_BIT
+.. doxygendefine:: TIMER_SMCR_ECE_BIT
+.. doxygendefine:: TIMER_SMCR_MSM_BIT
+
+.. doxygendefine:: TIMER_SMCR_ETP
+.. doxygendefine:: TIMER_SMCR_ECE
+.. doxygendefine:: TIMER_SMCR_ETPS
+.. doxygendefine:: TIMER_SMCR_ETPS_OFF
+.. doxygendefine:: TIMER_SMCR_ETPS_DIV2
+.. doxygendefine:: TIMER_SMCR_ETPS_DIV4
+.. doxygendefine:: TIMER_SMCR_ETPS_DIV8
+.. doxygendefine:: TIMER_SMCR_ETF
+.. doxygendefine:: TIMER_SMCR_MSM
+.. doxygendefine:: TIMER_SMCR_TS
+.. doxygendefine:: TIMER_SMCR_TS_ITR0
+.. doxygendefine:: TIMER_SMCR_TS_ITR1
+.. doxygendefine:: TIMER_SMCR_TS_ITR2
+.. doxygendefine:: TIMER_SMCR_TS_ITR3
+.. doxygendefine:: TIMER_SMCR_TS_TI1F_ED
+.. doxygendefine:: TIMER_SMCR_TS_TI1FP1
+.. doxygendefine:: TIMER_SMCR_TS_TI2FP2
+.. doxygendefine:: TIMER_SMCR_TS_ETRF
+.. doxygendefine:: TIMER_SMCR_SMS
+.. doxygendefine:: TIMER_SMCR_SMS_DISABLED
+.. doxygendefine:: TIMER_SMCR_SMS_ENCODER1
+.. doxygendefine:: TIMER_SMCR_SMS_ENCODER2
+.. doxygendefine:: TIMER_SMCR_SMS_ENCODER3
+.. doxygendefine:: TIMER_SMCR_SMS_RESET
+.. doxygendefine:: TIMER_SMCR_SMS_GATED
+.. doxygendefine:: TIMER_SMCR_SMS_TRIGGER
+.. doxygendefine:: TIMER_SMCR_SMS_EXTERNAL
+
+DMA/Interrupt enable register (DIER)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: TIMER_DIER_TDE_BIT
+.. doxygendefine:: TIMER_DIER_CC4DE_BIT
+.. doxygendefine:: TIMER_DIER_CC3DE_BIT
+.. doxygendefine:: TIMER_DIER_CC2DE_BIT
+.. doxygendefine:: TIMER_DIER_CC1DE_BIT
+.. doxygendefine:: TIMER_DIER_UDE_BIT
+.. doxygendefine:: TIMER_DIER_TIE_BIT
+.. doxygendefine:: TIMER_DIER_CC4IE_BIT
+.. doxygendefine:: TIMER_DIER_CC3IE_BIT
+.. doxygendefine:: TIMER_DIER_CC2IE_BIT
+.. doxygendefine:: TIMER_DIER_CC1IE_BIT
+.. doxygendefine:: TIMER_DIER_UIE_BIT
+
+.. doxygendefine:: TIMER_DIER_TDE
+.. doxygendefine:: TIMER_DIER_CC4DE
+.. doxygendefine:: TIMER_DIER_CC3DE
+.. doxygendefine:: TIMER_DIER_CC2DE
+.. doxygendefine:: TIMER_DIER_CC1DE
+.. doxygendefine:: TIMER_DIER_UDE
+.. doxygendefine:: TIMER_DIER_TIE
+.. doxygendefine:: TIMER_DIER_CC4IE
+.. doxygendefine:: TIMER_DIER_CC3IE
+.. doxygendefine:: TIMER_DIER_CC2IE
+.. doxygendefine:: TIMER_DIER_CC1IE
+.. doxygendefine:: TIMER_DIER_UIE
+
+Status register (SR)
+~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: TIMER_SR_CC4OF_BIT
+.. doxygendefine:: TIMER_SR_CC3OF_BIT
+.. doxygendefine:: TIMER_SR_CC2OF_BIT
+.. doxygendefine:: TIMER_SR_CC1OF_BIT
+.. doxygendefine:: TIMER_SR_BIF_BIT
+.. doxygendefine:: TIMER_SR_TIF_BIT
+.. doxygendefine:: TIMER_SR_COMIF_BIT
+.. doxygendefine:: TIMER_SR_CC4IF_BIT
+.. doxygendefine:: TIMER_SR_CC3IF_BIT
+.. doxygendefine:: TIMER_SR_CC2IF_BIT
+.. doxygendefine:: TIMER_SR_CC1IF_BIT
+.. doxygendefine:: TIMER_SR_UIF_BIT
+
+.. doxygendefine:: TIMER_SR_CC4OF
+.. doxygendefine:: TIMER_SR_CC3OF
+.. doxygendefine:: TIMER_SR_CC2OF
+.. doxygendefine:: TIMER_SR_CC1OF
+.. doxygendefine:: TIMER_SR_BIF
+.. doxygendefine:: TIMER_SR_TIF
+.. doxygendefine:: TIMER_SR_COMIF
+.. doxygendefine:: TIMER_SR_CC4IF
+.. doxygendefine:: TIMER_SR_CC3IF
+.. doxygendefine:: TIMER_SR_CC2IF
+.. doxygendefine:: TIMER_SR_CC1IF
+.. doxygendefine:: TIMER_SR_UIF
+
+Event generation register (EGR)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: TIMER_EGR_TG_BIT
+.. doxygendefine:: TIMER_EGR_CC4G_BIT
+.. doxygendefine:: TIMER_EGR_CC3G_BIT
+.. doxygendefine:: TIMER_EGR_CC2G_BIT
+.. doxygendefine:: TIMER_EGR_CC1G_BIT
+.. doxygendefine:: TIMER_EGR_UG_BIT
+
+.. doxygendefine:: TIMER_EGR_TG
+.. doxygendefine:: TIMER_EGR_CC4G
+.. doxygendefine:: TIMER_EGR_CC3G
+.. doxygendefine:: TIMER_EGR_CC2G
+.. doxygendefine:: TIMER_EGR_CC1G
+.. doxygendefine:: TIMER_EGR_UG
+
+Capture/compare mode registers, common values
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: TIMER_CCMR_CCS_OUTPUT
+.. doxygendefine:: TIMER_CCMR_CCS_INPUT_TI1
+.. doxygendefine:: TIMER_CCMR_CCS_INPUT_TI2
+.. doxygendefine:: TIMER_CCMR_CCS_INPUT_TRC
+
+Capture/compare mode register 1 (CCMR1)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: TIMER_CCMR1_OC2CE_BIT
+.. doxygendefine:: TIMER_CCMR1_OC2PE_BIT
+.. doxygendefine:: TIMER_CCMR1_OC2FE_BIT
+.. doxygendefine:: TIMER_CCMR1_OC1CE_BIT
+.. doxygendefine:: TIMER_CCMR1_OC1PE_BIT
+.. doxygendefine:: TIMER_CCMR1_OC1FE_BIT
+
+.. doxygendefine:: TIMER_CCMR1_OC2CE
+.. doxygendefine:: TIMER_CCMR1_OC2M
+.. doxygendefine:: TIMER_CCMR1_IC2F
+.. doxygendefine:: TIMER_CCMR1_OC2PE
+.. doxygendefine:: TIMER_CCMR1_OC2FE
+.. doxygendefine:: TIMER_CCMR1_IC2PSC
+.. doxygendefine:: TIMER_CCMR1_CC2S
+.. doxygendefine:: TIMER_CCMR1_CC2S_OUTPUT
+.. doxygendefine:: TIMER_CCMR1_CC2S_INPUT_TI1
+.. doxygendefine:: TIMER_CCMR1_CC2S_INPUT_TI2
+.. doxygendefine:: TIMER_CCMR1_CC2S_INPUT_TRC
+.. doxygendefine:: TIMER_CCMR1_OC1CE
+.. doxygendefine:: TIMER_CCMR1_OC1M
+.. doxygendefine:: TIMER_CCMR1_IC1F
+.. doxygendefine:: TIMER_CCMR1_OC1PE
+.. doxygendefine:: TIMER_CCMR1_OC1FE
+.. doxygendefine:: TIMER_CCMR1_IC1PSC
+.. doxygendefine:: TIMER_CCMR1_CC1S
+.. doxygendefine:: TIMER_CCMR1_CC1S_OUTPUT
+.. doxygendefine:: TIMER_CCMR1_CC1S_INPUT_TI1
+.. doxygendefine:: TIMER_CCMR1_CC1S_INPUT_TI2
+.. doxygendefine:: TIMER_CCMR1_CC1S_INPUT_TRC
+
+Capture/compare mode register 2 (CCMR2)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: TIMER_CCMR2_OC4CE_BIT
+.. doxygendefine:: TIMER_CCMR2_OC4PE_BIT
+.. doxygendefine:: TIMER_CCMR2_OC4FE_BIT
+.. doxygendefine:: TIMER_CCMR2_OC3CE_BIT
+.. doxygendefine:: TIMER_CCMR2_OC3PE_BIT
+.. doxygendefine:: TIMER_CCMR2_OC3FE_BIT
+
+.. doxygendefine:: TIMER_CCMR2_OC4CE
+.. doxygendefine:: TIMER_CCMR2_OC4M
+.. doxygendefine:: TIMER_CCMR2_IC2F
+.. doxygendefine:: TIMER_CCMR2_OC4PE
+.. doxygendefine:: TIMER_CCMR2_OC4FE
+.. doxygendefine:: TIMER_CCMR2_IC2PSC
+.. doxygendefine:: TIMER_CCMR2_CC4S
+.. doxygendefine:: TIMER_CCMR1_CC4S_OUTPUT
+.. doxygendefine:: TIMER_CCMR1_CC4S_INPUT_TI1
+.. doxygendefine:: TIMER_CCMR1_CC4S_INPUT_TI2
+.. doxygendefine:: TIMER_CCMR1_CC4S_INPUT_TRC
+.. doxygendefine:: TIMER_CCMR2_OC3CE
+.. doxygendefine:: TIMER_CCMR2_OC3M
+.. doxygendefine:: TIMER_CCMR2_IC1F
+.. doxygendefine:: TIMER_CCMR2_OC3PE
+.. doxygendefine:: TIMER_CCMR2_OC3FE
+.. doxygendefine:: TIMER_CCMR2_IC1PSC
+.. doxygendefine:: TIMER_CCMR2_CC3S
+.. doxygendefine:: TIMER_CCMR1_CC3S_OUTPUT
+.. doxygendefine:: TIMER_CCMR1_CC3S_INPUT_TI1
+.. doxygendefine:: TIMER_CCMR1_CC3S_INPUT_TI2
+.. doxygendefine:: TIMER_CCMR1_CC3S_INPUT_TRC
+
+Capture/compare enable register (CCER)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: TIMER_CCER_CC4P_BIT
+.. doxygendefine:: TIMER_CCER_CC4E_BIT
+.. doxygendefine:: TIMER_CCER_CC3P_BIT
+.. doxygendefine:: TIMER_CCER_CC3E_BIT
+.. doxygendefine:: TIMER_CCER_CC2P_BIT
+.. doxygendefine:: TIMER_CCER_CC2E_BIT
+.. doxygendefine:: TIMER_CCER_CC1P_BIT
+.. doxygendefine:: TIMER_CCER_CC1E_BIT
+
+.. doxygendefine:: TIMER_CCER_CC4P
+.. doxygendefine:: TIMER_CCER_CC4E
+.. doxygendefine:: TIMER_CCER_CC3P
+.. doxygendefine:: TIMER_CCER_CC3E
+.. doxygendefine:: TIMER_CCER_CC2P
+.. doxygendefine:: TIMER_CCER_CC2E
+.. doxygendefine:: TIMER_CCER_CC1P
+.. doxygendefine:: TIMER_CCER_CC1E
+
+Break and dead-time register (BDTR)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: TIMER_BDTR_MOE_BIT
+.. doxygendefine:: TIMER_BDTR_AOE_BIT
+.. doxygendefine:: TIMER_BDTR_BKP_BIT
+.. doxygendefine:: TIMER_BDTR_BKE_BIT
+.. doxygendefine:: TIMER_BDTR_OSSR_BIT
+.. doxygendefine:: TIMER_BDTR_OSSI_BIT
+
+.. doxygendefine:: TIMER_BDTR_MOE
+.. doxygendefine:: TIMER_BDTR_AOE
+.. doxygendefine:: TIMER_BDTR_BKP
+.. doxygendefine:: TIMER_BDTR_BKE
+.. doxygendefine:: TIMER_BDTR_OSSR
+.. doxygendefine:: TIMER_BDTR_OSSI
+.. doxygendefine:: TIMER_BDTR_LOCK
+.. doxygendefine:: TIMER_BDTR_LOCK_OFF
+.. doxygendefine:: TIMER_BDTR_LOCK_LEVEL1
+.. doxygendefine:: TIMER_BDTR_LOCK_LEVEL2
+.. doxygendefine:: TIMER_BDTR_LOCK_LEVEL3
+.. doxygendefine:: TIMER_BDTR_DTG
+
+DMA control register (DCR)
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: TIMER_DCR_DBL
+.. doxygendefine:: TIMER_DCR_DBL_1BYTE
+.. doxygendefine:: TIMER_DCR_DBL_2BYTE
+.. doxygendefine:: TIMER_DCR_DBL_3BYTE
+.. doxygendefine:: TIMER_DCR_DBL_4BYTE
+.. doxygendefine:: TIMER_DCR_DBL_5BYTE
+.. doxygendefine:: TIMER_DCR_DBL_6BYTE
+.. doxygendefine:: TIMER_DCR_DBL_7BYTE
+.. doxygendefine:: TIMER_DCR_DBL_8BYTE
+.. doxygendefine:: TIMER_DCR_DBL_9BYTE
+.. doxygendefine:: TIMER_DCR_DBL_10BYTE
+.. doxygendefine:: TIMER_DCR_DBL_11BYTE
+.. doxygendefine:: TIMER_DCR_DBL_12BYTE
+.. doxygendefine:: TIMER_DCR_DBL_13BYTE
+.. doxygendefine:: TIMER_DCR_DBL_14BYTE
+.. doxygendefine:: TIMER_DCR_DBL_15BYTE
+.. doxygendefine:: TIMER_DCR_DBL_16BYTE
+.. doxygendefine:: TIMER_DCR_DBL_17BYTE
+.. doxygendefine:: TIMER_DCR_DBL_18BYTE
+.. doxygendefine:: TIMER_DCR_DBA
+.. doxygendefine:: TIMER_DCR_DBA_CR1
+.. doxygendefine:: TIMER_DCR_DBA_CR2
+.. doxygendefine:: TIMER_DCR_DBA_SMCR
+.. doxygendefine:: TIMER_DCR_DBA_DIER
+.. doxygendefine:: TIMER_DCR_DBA_SR
+.. doxygendefine:: TIMER_DCR_DBA_EGR
+.. doxygendefine:: TIMER_DCR_DBA_CCMR1
+.. doxygendefine:: TIMER_DCR_DBA_CCMR2
+.. doxygendefine:: TIMER_DCR_DBA_CCER
+.. doxygendefine:: TIMER_DCR_DBA_CNT
+.. doxygendefine:: TIMER_DCR_DBA_PSC
+.. doxygendefine:: TIMER_DCR_DBA_ARR
+.. doxygendefine:: TIMER_DCR_DBA_RCR
+.. doxygendefine:: TIMER_DCR_DBA_CCR1
+.. doxygendefine:: TIMER_DCR_DBA_CCR2
+.. doxygendefine:: TIMER_DCR_DBA_CCR3
+.. doxygendefine:: TIMER_DCR_DBA_CCR4
+.. doxygendefine:: TIMER_DCR_DBA_BDTR
+.. doxygendefine:: TIMER_DCR_DBA_DCR
+.. doxygendefine:: TIMER_DCR_DBA_DMAR
diff --git a/docs/source/libmaple/api/usart.rst b/docs/source/libmaple/api/usart.rst
new file mode 100644
index 0000000..68f2c37
--- /dev/null
+++ b/docs/source/libmaple/api/usart.rst
@@ -0,0 +1,197 @@
+.. highlight:: c
+.. _libmaple-usart:
+
+``usart.h``
+===========
+
+Universal Synchronous/Asynchronous Receiver/Transmitter (USART, or
+commonly *serial port*) support.
+
+.. contents:: Contents
+ :local:
+
+Types
+-----
+
+.. doxygenstruct:: usart_reg_map
+.. doxygenstruct:: usart_dev
+
+Devices
+-------
+
+.. doxygenvariable:: USART1
+.. doxygenvariable:: USART2
+.. doxygenvariable:: USART3
+.. doxygenvariable:: UART4
+.. doxygenvariable:: UART5
+
+Functions
+---------
+
+.. doxygenfunction:: usart_init
+.. doxygenfunction:: usart_set_baud_rate
+.. doxygenfunction:: usart_enable
+.. doxygenfunction:: usart_disable
+.. doxygenfunction:: usart_disable_all
+.. doxygenfunction:: usart_foreach
+.. doxygenfunction:: usart_rx
+.. doxygenfunction:: usart_tx
+.. doxygenfunction:: usart_putudec
+.. doxygenfunction:: usart_putc
+.. doxygenfunction:: usart_putstr
+.. doxygenfunction:: usart_getc
+.. doxygenfunction:: usart_data_available
+.. doxygenfunction:: usart_reset_rx
+
+Register Map Base Pointers
+--------------------------
+
+.. doxygendefine:: USART1_BASE
+.. doxygendefine:: USART2_BASE
+.. doxygendefine:: USART3_BASE
+.. doxygendefine:: UART4_BASE
+.. doxygendefine:: UART5_BASE
+
+Register Bit Definitions
+------------------------
+
+Status Register
+~~~~~~~~~~~~~~~
+
+.. doxygendefine:: USART_SR_CTS_BIT
+.. doxygendefine:: USART_SR_LBD_BIT
+.. doxygendefine:: USART_SR_TXE_BIT
+.. doxygendefine:: USART_SR_TC_BIT
+.. doxygendefine:: USART_SR_RXNE_BIT
+.. doxygendefine:: USART_SR_IDLE_BIT
+.. doxygendefine:: USART_SR_ORE_BIT
+.. doxygendefine:: USART_SR_NE_BIT
+.. doxygendefine:: USART_SR_FE_BIT
+.. doxygendefine:: USART_SR_PE_BIT
+
+.. doxygendefine:: USART_SR_CTS
+.. doxygendefine:: USART_SR_LBD
+.. doxygendefine:: USART_SR_TXE
+.. doxygendefine:: USART_SR_TC
+.. doxygendefine:: USART_SR_RXNE
+.. doxygendefine:: USART_SR_IDLE
+.. doxygendefine:: USART_SR_ORE
+.. doxygendefine:: USART_SR_NE
+.. doxygendefine:: USART_SR_FE
+.. doxygendefine:: USART_SR_PE
+
+Data register
+~~~~~~~~~~~~~
+
+.. doxygendefine:: USART_DR_DR
+
+Baud Rate Register
+~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: USART_BRR_DIV_MANTISSA
+.. doxygendefine:: USART_BRR_DIV_FRACTION
+
+Control Register 1
+~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: USART_CR1_UE_BIT
+.. doxygendefine:: USART_CR1_M_BIT
+.. doxygendefine:: USART_CR1_WAKE_BIT
+.. doxygendefine:: USART_CR1_PCE_BIT
+.. doxygendefine:: USART_CR1_PS_BIT
+.. doxygendefine:: USART_CR1_PEIE_BIT
+.. doxygendefine:: USART_CR1_TXEIE_BIT
+.. doxygendefine:: USART_CR1_TCIE_BIT
+.. doxygendefine:: USART_CR1_RXNEIE_BIT
+.. doxygendefine:: USART_CR1_IDLEIE_BIT
+.. doxygendefine:: USART_CR1_TE_BIT
+.. doxygendefine:: USART_CR1_RE_BIT
+.. doxygendefine:: USART_CR1_RWU_BIT
+.. doxygendefine:: USART_CR1_SBK_BIT
+
+.. doxygendefine:: USART_CR1_UE
+.. doxygendefine:: USART_CR1_M
+.. doxygendefine:: USART_CR1_WAKE
+.. doxygendefine:: USART_CR1_WAKE_IDLE
+.. doxygendefine:: USART_CR1_WAKE_ADDR
+.. doxygendefine:: USART_CR1_PCE
+.. doxygendefine:: USART_CR1_PS
+.. doxygendefine:: USART_CR1_PS_EVEN
+.. doxygendefine:: USART_CR1_PS_ODD
+.. doxygendefine:: USART_CR1_PEIE
+.. doxygendefine:: USART_CR1_TXEIE
+.. doxygendefine:: USART_CR1_TCIE
+.. doxygendefine:: USART_CR1_RXNEIE
+.. doxygendefine:: USART_CR1_IDLEIE
+.. doxygendefine:: USART_CR1_TE
+.. doxygendefine:: USART_CR1_RE
+.. doxygendefine:: USART_CR1_RWU
+.. doxygendefine:: USART_CR1_RWU_ACTIVE
+.. doxygendefine:: USART_CR1_RWU_MUTE
+.. doxygendefine:: USART_CR1_SBK
+
+Control Register 2
+~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: USART_CR2_LINEN_BIT
+.. doxygendefine:: USART_CR2_CLKEN_BIT
+.. doxygendefine:: USART_CR2_CPOL_BIT
+.. doxygendefine:: USART_CR2_CPHA_BIT
+.. doxygendefine:: USART_CR2_LBCL_BIT
+.. doxygendefine:: USART_CR2_LBDIE_BIT
+.. doxygendefine:: USART_CR2_LBDL_BIT
+
+.. doxygendefine:: USART_CR2_LINEN
+.. doxygendefine:: USART_CR2_STOP
+.. doxygendefine:: USART_CR2_STOP_BITS_1
+.. doxygendefine:: USART_CR2_STOP_BITS_POINT_5
+.. doxygendefine:: USART_CR2_STOP_BITS_1_POINT_5
+.. doxygendefine:: USART_CR2_STOP_BITS_2
+.. doxygendefine:: USART_CR2_CLKEN
+.. doxygendefine:: USART_CR2_CPOL
+.. doxygendefine:: USART_CR2_CPOL_LOW
+.. doxygendefine:: USART_CR2_CPOL_HIGH
+.. doxygendefine:: USART_CR2_CPHA
+.. doxygendefine:: USART_CR2_CPHA_FIRST
+.. doxygendefine:: USART_CR2_CPHA_SECOND
+.. doxygendefine:: USART_CR2_LBCL
+.. doxygendefine:: USART_CR2_LBDIE
+.. doxygendefine:: USART_CR2_LBDL
+.. doxygendefine:: USART_CR2_LBDL_10_BIT
+.. doxygendefine:: USART_CR2_LBDL_11_BIT
+.. doxygendefine:: USART_CR2_ADD
+
+Control Register 3
+~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: USART_CR3_CTSIE_BIT
+.. doxygendefine:: USART_CR3_CTSE_BIT
+.. doxygendefine:: USART_CR3_RTSE_BIT
+.. doxygendefine:: USART_CR3_DMAT_BIT
+.. doxygendefine:: USART_CR3_DMAR_BIT
+.. doxygendefine:: USART_CR3_SCEN_BIT
+.. doxygendefine:: USART_CR3_NACK_BIT
+.. doxygendefine:: USART_CR3_HDSEL_BIT
+.. doxygendefine:: USART_CR3_IRLP_BIT
+.. doxygendefine:: USART_CR3_IREN_BIT
+.. doxygendefine:: USART_CR3_EIE_BIT
+
+.. doxygendefine:: USART_CR3_CTSIE
+.. doxygendefine:: USART_CR3_CTSE
+.. doxygendefine:: USART_CR3_RTSE
+.. doxygendefine:: USART_CR3_DMAT
+.. doxygendefine:: USART_CR3_DMAR
+.. doxygendefine:: USART_CR3_SCEN
+.. doxygendefine:: USART_CR3_NACK
+.. doxygendefine:: USART_CR3_HDSEL
+.. doxygendefine:: USART_CR3_IRLP
+.. doxygendefine:: USART_CR3_IRLP_NORMAL
+.. doxygendefine:: USART_CR3_IRLP_LOW_POWER
+.. doxygendefine:: USART_CR3_IREN
+.. doxygendefine:: USART_CR3_EIE
+
+Guard Time and Prescaler Register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. doxygendefine:: USART_GTPR_GT
+.. doxygendefine:: USART_GTPR_PSC
diff --git a/docs/source/libmaple/api/util.rst b/docs/source/libmaple/api/util.rst
new file mode 100644
index 0000000..54377c0
--- /dev/null
+++ b/docs/source/libmaple/api/util.rst
@@ -0,0 +1,54 @@
+.. highlight:: c
+.. _libmaple-util:
+
+``<libmaple/util.h>``
+=====================
+
+.. TODO [0.2.0?] clean this up.
+
+Miscellaneous utility macros and procedures.
+
+.. contents:: Contents
+ :local:
+
+Bit Manipulation
+----------------
+
+The following macros are useful for bit manipulation.
+
+.. doxygendefine:: BIT
+.. doxygendefine:: BIT_MASK_SHIFT
+.. doxygendefine:: GET_BITS
+.. doxygendefine:: IS_POWER_OF_TWO
+
+Failure Routines
+----------------
+
+``throb()`` is called by various routines to throb a built-in
+LED. **Usually, you shouldn't call it yourself**; use something like
+``ASSERT(0)`` (or the libc ``abort()`` function) instead.
+
+.. doxygenfunction:: throb
+
+Asserts and Debug Levels
+------------------------
+
+The level of libmaple's assertion support is determined by
+``DEBUG_LEVEL``, as follows:
+
+.. doxygendefine:: DEBUG_LEVEL
+
+The current assert macros are ``ASSERT()`` and ``ASSERT_FAULT()``.
+``ASSERT()`` is checked when ``DEBUG_LEVEL >= DEBUG_ALL``.
+``ASSERT_FAULT()`` is checked whenever ``DEBUG_LEVEL >= DEBUG_FAULT``.
+
+As explained above, an assert macro is checked when the current
+``DEBUG_LEVEL`` is high enough. If the debug level is too low, the
+macro expands into a no-op that gets compiled away.
+
+If an assertion fails, execution is halted at the point of the failed
+assertion. When libmaple has been configured properly (Wirish
+performs this configuration by default), the built-in LED throbs in a
+smooth pattern to signal the failed assertion (using
+:c:func:`throb()`), and the file and line where the assert failed are
+transmitted to the user as detailed in :ref:`lang-assert`.
diff --git a/docs/source/libmaple/apis.rst b/docs/source/libmaple/apis.rst
new file mode 100644
index 0000000..31f4902
--- /dev/null
+++ b/docs/source/libmaple/apis.rst
@@ -0,0 +1,14 @@
+.. _libmaple-apis:
+
+``libmaple`` API Index
+======================
+
+This is the master index for libmaple proper's APIs.
+
+**Contents**
+
+.. toctree::
+ :maxdepth: 1
+ :glob:
+
+ api/*
diff --git a/docs/source/libmaple/coding-standard.rst b/docs/source/libmaple/coding-standard.rst
new file mode 100644
index 0000000..9ed56cc
--- /dev/null
+++ b/docs/source/libmaple/coding-standard.rst
@@ -0,0 +1,422 @@
+.. _libmaple-coding-standard:
+
+Coding Standard
+===============
+
+This page documents the coding standard for :ref:`libmaple`. It's
+intended as a guide for how you should structure any code you would
+like included into the LeafLabs releases of libmaple.
+
+LeafLabs team members are required to follow these when producing new
+code. Community contributors to libmaple are strongly encouraged to
+do so; following these rules will greatly increase the probability
+that your patches will be folded in.
+
+In general, follow this guide unless there's a very good reason not
+to. Laziness doesn't count as a good reason. Most, if not all, of
+these decisions are entirely arbitrary, but it's important for
+readability that we be consistent. (If you notice an inconsistency,
+you should fix it).
+
+Note that the file ``.dir-locals.el`` in the libmaple root directory
+already ensures that many of these standards are followed by default
+in Emacs (but not on Windows, where it would need to be named
+``_dir_locals.el``, and no way, man). There's also some elisp
+scattered about this file which will provide you additional help.
+
+Configuration for other editors (vim, etc.) would be nice!
+
+.. contents:: Contents
+ :local:
+
+License
+-------
+
+.. highlight:: scheme
+
+Put an MIT license at the beginning of the file (look at any of our
+source files for an example). Copyright should go either to you or to
+LeafLabs, LLC.
+
+Emacs: if you don't like seeing the license, you should use elide-head
+(which will hide it for you). You can use the following::
+
+ (require 'elide-head)
+ (setq programming-mode-hooks '(c-mode-hook c++-mode-hook))
+ (add-to-list 'elide-head-headers-to-hide
+ '("The MIT License" . "DEALINGS IN\n [*] THE SOFTWARE"))
+ (add-to-list 'elide-head-headers-to-hide
+ '("The MIT License" . "DEALINGS IN THE\n...SOFTWARE"))
+ (dolist (hook programming-mode-hooks)
+ (add-hook hook (lambda () (elide-head))))
+
+Whitespace
+----------
+
+TextMate users may find `this bundle
+<https://github.com/glennr/uber-glory-tmbundle>`_ useful for
+automatically converting tabs to spaces and removing trailing
+whitespace at save time.
+
+- 4 space indents (set in ``.dir-locals.el``).
+
+- Unix newlines.
+
+- No tab characters (set in ``.dir-locals.el``).
+
+- No trailing whitespace. For help getting this (and no tab
+ characters) done automatically in Emacs, you can use
+ `code-fascism.el <https://github.com/mbolivar/code-fascism>`_.
+
+- Files end in exactly one newline. The presence of a newline at EOF
+ is already done by ``c-require-final-newline`` in recent versions of
+ Emacs.
+
+- Exactly two newlines separate source paragraphs (you do separate
+ your code into paragraphs, don't you?).
+
+- The first line in a function is non-blank.
+
+.. highlight:: cpp
+
+- Exactly one space after ``if``, ``else``, ``for``, and ``while``,
+ before the following ``{`` or ``(``. One space before ``else``,
+ after the preceding ``}``. For example::
+
+ // This is good; we like this:
+ if (foo) {
+ while (quux) {
+ bar();
+ }
+ } else {
+ baz();
+ }
+
+ // THIS IS BAD! DON'T DO THIS:
+ if(foo){
+ while(quux){
+ bar();
+ }
+ }else{
+ baz();
+ }
+
+- Exactly one space in between binary arithmetic, logical, and
+ comparison operators and their operands. Examples::
+
+ // This is good:
+ int x = a + b * (c - d);
+ if (x != 0 && a > 7) {
+ SerialUSB.println(x);
+ }
+
+ // THIS IS BAD!
+ int x = a+b*(c-d);
+ if (x!=0 && a>7) {
+ SerialUSB.println(x);
+ }
+
+ // This is good:
+ uint32 adc_data = ADC1_BASE->DR;
+ SerialUSB.println(adc_data);
+
+ // THIS IS BAD!
+ uint32 adc_data = ADC1_BASE -> DR;
+ SerialUSB . println(adc_data);
+
+- No space between a unary operator and its operand. Examples::
+
+ // Good:
+ x++;
+
+ // BAD!
+ x ++;
+
+ // Good:
+ y = -x;
+
+ // BAD!
+ y = - x;
+
+- If you need to break up a long line:
+
+ * Prefer to break up long expressions after a binary operator. Example::
+
+ // Good:
+ if (some_really_long_conditional_wow_this_really_goes_on_forever ||
+ maybe_something_else_could_happen_too) {
+ ...
+ }
+
+ // BAD!
+ if (some_really_long_conditional_wow_this_really_goes_on_forever
+ || maybe_something_else_could_happen_too) {
+ ...
+ }
+
+ * When breaking up a function's arguments over multiple lines, align
+ the arguments on subsequent lines with the first argument.
+ Example::
+
+ // Good:
+ return_type value_i_got = function_with_a_really_long_name(argument1,
+ argument2,
+ argument3);
+
+ // BAD!
+ return_type value_i_got = function_with_a_really_long_name(argument1,
+ argument2,
+ argument3);
+
+ // BAD!
+ return_type value_i_got = function_with_a_really_long_name(argument1,
+ argument2,
+ argument3);
+
+- In function invocations, no space in between the function name and
+ the opening parenthesis. Example::
+
+ // Good:
+ SerialUSB.println("Hello, world!");
+
+ // BAD!
+ SerialUSB.println ("Hello, world!");
+
+- Don't indent C code within a conditionally-compiled ``extern "C"``
+ block. Example::
+
+ // Good:
+ #ifdef __cplusplus
+ extern "C"{
+ #endif
+
+ void some_c_function(void);
+
+ #ifdef __cplusplus
+ } // extern "C"
+ #endif
+
+ // BAD!
+ #ifdef __cplusplus
+ extern "C"{
+ #endif
+
+ void some_c_function(void);
+
+ #ifdef __cplusplus
+ } // extern "C"
+ #endif
+
+ Emacs does the "bad" behavior by default, which can be very
+ annoying. You can turn this off with ::
+
+ (defun c-mode-inextern-lang-hook ()
+ (setcdr (assq 'inextern-lang c-offsets-alist) '-))
+ (add-hook 'c-mode-hook c-mode-inextern-lang-hook)
+
+Comments
+--------
+
+.. highlight:: c++
+
+- Multi-line comments are pretty flexible. Any of these is fine::
+
+ /* Comment starts here.
+ * Continued lines have a '*' before them.
+ * The comment can end after the last line.
+ */
+
+ /* Comment starts here.
+ * The comment can end on the same line. */
+
+ /*
+ * You can also place a newline after the opening "/*".
+ */
+
+- Doxygen comments are multi-line comments that begin with ``/**``
+ instead.
+
+- Single-line comments are up to you.
+
+Braces
+------
+
+- Mostly `1TBS
+ <http://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS>`_. The
+ only difference is that the opening brace of a function's definition
+ occurs exactly one space character after the closing parenthesis in
+ that function's parameter list. Example::
+
+ void func(void) {
+ ...
+ }
+
+Naming conventions
+------------------
+
+We'll handle the usual casing/underscore debate as follows.
+
+- First, ``Dont_Mix_Like_This``, because ``It_Looks_Really_Ugly``, ok?
+ [There's been some debate about this, and some exceptions are
+ already grandfathered in, so in order to settle it, let's call this
+ a "recommendation" instead of "requirement".]
+
+- Variables: Use underscores to separate words in C identifiers::
+
+ int some_example_name;
+
+ User-facing C++ variables should be camel cased
+ (``thisIsAnExample``, ``boardPWMPins``, etc.), for consistency with
+ the Arduino style. It's probably a good idea for you to case
+ non-user facing C++ variables in the C style; this will help
+ disambiguate what's part of the Wirish API and what's not.
+
+- Classes: Pascal case. So ``ThisIsAClassName``, but ``thisIsNot``,
+ ``this_is_not``, and ``Dont_You_DareTryANYTHING_STUPID``.
+
+- Functions: C functions are all lowercase, and words are separated by
+ underscores. C++ method names are camel cased.
+
+- Structs: Usually like variables (``adc_dev``, ``adc_reg_map``,
+ etc.), but it's not crucial. Don't feel obliged to put ``_t`` at
+ the end of the type name; we don't.
+
+- Macros and constants: all caps, separated by underscores. C++
+ variables with the ``const`` qualifier generally aren't considered
+ "constants" for the purposes of this rule; i.e., they are cased
+ according to the rules for variables. We make an exception for
+ ``PIN_MAP``, because it's the central Wirish data structure.
+
+- foo.h gets ``#ifdef``\ 'ed to ``_FOO_H_``.
+
+- Acronyms: The case of letters in an acronym is determined by the
+ case of the first letter in the acronym, which is determined by
+ following the above rules. Examples::
+
+ // Good:
+ void usb_func() { ... }
+ void frob_usb_disc() { ... }
+ class SomethingUSB {
+ void usbInit();
+ void initUSB();
+ };
+
+ // BAD:
+ class BadUsb { ... }; // say "GoodUSB" instead
+ void swizzle_USB_disc() { ... } // say "swizzle_usb_disc" instead
+
+Documentation
+-------------
+
+- Doxygen comments on every user-facing function and type.
+ Additionally, individually document the fields and enumerator values
+ of nontrivial user-facing structs and enums. See any register map
+ type's definition for an example.
+
+- For libmaple proper, you don't need comments for each register bit
+ definition, since that's just repeating information better obtained
+ by reading ST RM0008.
+
+- Doxygen comments generally only belong on types, functions,
+ etc. that are part of the public user-facing API.
+
+ This essentially means that if what you're writing is going to be
+ documented under http://leaflabs.com/docs/ (i.e., if there's `Sphinx
+ documentation <http://sphinx.pocoo.org/>`_ for it in the
+ `leaflabs-docs <https://github.com/leaflabs/leaflabs-docs>`_
+ repository), then you need to write Doxygen comments. Further,
+ those Sphinx docs should use Breathe to pull the Doxygen out. (For
+ more information on this, see the `leaflabs-docs README
+ <https://raw.github.com/leaflabs/leaflabs-docs/master/README>`_).
+
+ Because Breathe isn't totally mature yet, you won't always be able
+ to do this. In these cases, document the code "manually" using the
+ Sphinx `C and C++ domains
+ <http://sphinx.pocoo.org/domains.html#the-c-domain>`_. This should
+ be avoided if at all possible, since it creates a maintenance burden
+ of documenting things in two places at once, and makes it easier for
+ documentation to go stale.
+
+ If you do have to document something manually, put a comment in the
+ source file informing future maintainers about it, so they'll pay
+ extra attention when making changes.
+
+- When adding peripheral support, it would be nice if you put
+ longer-form comments into the libmaple ``notes/`` directory, with a
+ comment in the corresponding .h file referring to it. See the
+ :ref:`dac.h <libmaple-dac>` source for an example.
+
+ This lets us keep the source files relatively free of "introductory"
+ material, while allowing new readers a convenient starting point.
+ These longer-form notes also have a habit of turning into official,
+ user-facing documentation (or `wiki <http://wiki.leaflabs.com>`_
+ pages).
+
+- **For libmaple proper**, the convention is to document any
+ user-facing function at the point where it is defined. In
+ particular, this means you should document an externally-linked
+ function defined in a .c file in that .c file, not in the header
+ file where it is declared to the user.
+
+ **For Wirish**, the convention is to put the documentation in the
+ header file where the function is declared.
+
+General Formatting
+------------------
+
+.. highlight:: scheme
+
+- Keep it 80-column clean.
+
+ Emacs users: this means that the largest column number is 79. You
+ should turn on column number mode to help you out::
+
+ (column-number-mode 1)
+
+ You can get more help from `lineker-mode
+ <http://www.helsinki.fi/~sjpaavol/programs/lineker.el>`_. Just put
+ lineker.el somewhere in your load-path, and::
+
+ (require 'lineker)
+ (dolist (hook '(c-mode-hook c++-mode-hook))
+ (add-hook hook (lambda () (lineker-mode 1))))
+
+.. highlight:: cpp
+
+Language Features
+-----------------
+
+In libmaple proper, aim for C99 compatibility. Some GCC extensions
+are OK, but `don't get crazy <http://www.youtube.com/watch?v=jZkdcYlOn5M>`_.
+
+Explicitly approved GCC extensions:
+
+ * `asm volatile <http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html>`_
+
+ * `Nested functions <http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html>`_
+
+In Wirish, generally be very conservative when using C++ features that
+aren't part of C. We are forced to use C++ for Arduino compatibility
+(and the general Arduino style of conflating objects and libraries),
+but it's an angry beast, and we don't want to provoke it. **The
+mantra is "C with classes"**.
+
+Explicitly approved C++ features:
+
+ * Initializers that aren't constant; e.g. the ``gpio_dev*`` values
+ in a ``PIN_MAP``.
+
+ * Default arguments: e.g., the timeout argument in
+ :ref:`lang-waitforbuttonpress`.
+
+Explicitly forbidden C++ features:
+
+ * Templates
+
+Conditionally allowed C++ features:
+
+ * Operator overloading: Never allowed when it's just for style.
+ Probably fine when you're implementing a class that models a
+ mathematical structure, and you'd like to implement
+ e.g. ``operator+()``.
+
diff --git a/docs/source/libmaple/contributing.rst b/docs/source/libmaple/contributing.rst
new file mode 100644
index 0000000..25c6c17
--- /dev/null
+++ b/docs/source/libmaple/contributing.rst
@@ -0,0 +1,176 @@
+.. _libmaple-contributing:
+
+Contributing to libmaple
+========================
+
+First of all, thanks! Community contributions are what makes open
+source great.
+
+If your patch is minor (you've found a typo, you've added a new
+function, etc.), feel free to just make a `forum post
+<http://forums.leaflabs.com>`_ describing your changes.
+
+If your changes are larger (you wrote a new library, you added support
+for a new peripheral, etc.), we'd prefer you submit a pull request on
+GitHub or send us a nicely-formatted patch via email.
+
+.. contents:: Contents
+ :local:
+
+.. _libmaple-faq-patches-preparing:
+
+Preparing Your Patch
+--------------------
+
+Before submitting a patch, please make sure it complies with the
+:ref:`coding standard <libmaple-coding-standard>`. Consistent style throughout
+the source tree is an important implementation objective for us, and a
+patch that doesn't comply with the coding standard we've set forth is
+likely to be sent back until it follows the standard.
+
+We would prefer if you release each new file you submit under the `MIT
+license <http://www.opensource.org/licenses/mit-license.php>`_. See
+e.g. `bkp.h
+<https://github.com/leaflabs/libmaple/blob/master/libmaple/bkp.h#L1>`_
+for an example, and the coding standard for more details. Code
+released under the `Lesser GPL
+<http://www.gnu.org/copyleft/lesser.html>`_ may be accepted for
+Wirish, but will almost certainly be rejected for libmaple proper. We
+will not accept patches released under the `GPL
+<http://www.gnu.org/licenses/gpl.html>`_.
+
+**We're not against the GPL**! It just doesn't suit our purposes for
+libmaple. If you're interested in a GPLed library for ST
+microcontrollers, check out `libopenstm32
+<http://www.hermann-uwe.de/blog/libopenstm32-a-free-software-firmware-library-for-stm32-arm-cortex-m3-microcontrollers>`_.
+Also note that :ref:`libraries <libraries>` released under the GPL are
+fine, we just don't want any core libmaple or Wirish code to be GPLed.
+
+.. _libmaple-faq-patches-github:
+
+Submitting Via GitHub Pull Request (Preferred)
+----------------------------------------------
+
+The most convenient way for you to contribute patches is to submit a
+pull request on `GitHub <https://github.com>`_. Github provides
+excellent code review interfaces, which will make it easy for us at
+LeafLabs to communicate with you (and each other) about your patch.
+It also makes it easy for us to merge your patch into the libmaple
+source tree when the time comes.
+
+The steps to submit a pull request are as follows:
+
+1. If you don't already have one, get a `GitHub account
+ <https://github.com/plans>`_ (free).
+
+2. Fork libmaple, then clone your fork to the computer you code on.
+ GitHub provides detailed instructions on `forking and cloning a
+ repository <http://help.github.com/fork-a-repo/>`_.
+
+3. Push your commits to your GitHub libmaple fork (see instructions
+ linked in Step 2 for a step-by-step walkthrough on how to do this).
+
+ Please add a signed-off-by line to your commits which certify your
+ `developer certificate of origin
+ <http://elinux.org/Developer_Certificate_Of_Origin>`_ [#fcert]_.
+ For example, if your name is "John Smith", and your email address
+ is "jsmith@example.com", just include the following line at the
+ bottom of your commit messages:
+
+ ``Signed-off-by: John Smith <jsmith@example.com>``
+
+ If you've configured Git to know your name and email, you can
+ instruct it to insert this line automatically by calling ``git
+ commit`` with the ``-s`` flag.
+
+4. `Submit a pull request <http://help.github.com/pull-requests/>`_ to
+ the LeafLabs version of libmaple.
+
+.. _libmaple-faq-patches-email:
+
+Submitting Via Email
+--------------------
+
+If you're unfamiliar with Git or would prefer not to use GitHub, you
+can always send us a patch via email at info@leaflabs.com. We'd love
+it if you used the `Linux kernel patch format
+<http://linux.yyz.us/patch-format.html>`_, but please at least include
+the following information in your email:
+
+1. How you generated your patch (arguments to ``diff``, etc.)
+
+2. What git branch/commit or libmaple version your patch applies to
+
+3. A one-line summary of your changes, along with any other details
+ you think we should know.
+
+4. A sign-off line certifying your `developer certificate of origin
+ <http://elinux.org/Developer_Certificate_Of_Origin>`_ [#fcert]_.
+
+.. _libmaple-git-resources:
+
+Git Resources
+-------------
+
+If you'd like to learn more about Git, we recommend the following
+resources:
+
+* `The Git Community Book <http://book.git-scm.com/index.html>`_: A
+ collaboratively edited book on Git.
+
+* `Pro Git <http://progit.org/book/>`_: despite its title, this is a
+ fairly beginner-friendly source of information.
+
+* `Git - Revision Control Perfected (Linux Journal)
+ <http://www.linuxjournal.com/content/git-revision-control-perfected>`_:
+ Despite a title that makes it sound like it was written by a
+ marketing department, this is a very good introductory article on
+ basic Git concepts, and a solid primer on Git's internals.
+
+- `GitPhraseBook (openembedded.org)
+ <http://www.openembedded.org/index.php/GitPhraseBook>`_: A
+ cookbook-style list of common Git problems and their solutions.
+
+* `Understanding Git Conceptually
+ <http://www.eecs.harvard.edu/~cduan/technical/git/>`_: a good,
+ introductory tutorial on Git's fundamental concepts.
+
+* `Git for Computer Scientists
+ <http://eagain.net/articles/git-for-computer-scientists/>`_: if
+ you're comfortable with directed acyclic graphs, this resource
+ explains Git's functionality in graph-theoretic terms.
+
+.. highlight:: text
+
+.. rubric:: Footnotes
+
+.. [#fcert] Including this line indicates that you certify the following::
+
+ Developer's Certificate of Origin 1.1
+
+ By making a contribution to this project, I certify that:
+
+ (a) The contribution was created in whole or in part by me and I
+ have the right to submit it under the open source license
+ indicated in the file; or
+
+ (b) The contribution is based upon previous work that, to the best
+ of my knowledge, is covered under an appropriate open source
+ license and I have the right under that license to submit that
+ work with modifications, whether created in whole or in part
+ by me, under the same open source license (unless I am
+ permitted to submit under a different license), as indicated
+ in the file; or
+
+ (c) The contribution was provided directly to me by some other
+ person who certified (a), (b) or (c) and I have not modified
+ it.
+
+ (d) I understand and agree that this project and the contribution
+ are public and that a record of the contribution (including all
+ personal information I submit with it, including my sign-off) is
+ maintained indefinitely and may be redistributed consistent with
+ this project or the open source license(s) involved.
+
+ This may seem arbitrary, but it helps ensure that libmaple
+ remains open source.
diff --git a/docs/source/libmaple/overview.rst b/docs/source/libmaple/overview.rst
new file mode 100644
index 0000000..006f1d8
--- /dev/null
+++ b/docs/source/libmaple/overview.rst
@@ -0,0 +1,516 @@
+.. highlight:: c
+
+.. _libmaple-overview:
+
+Overview
+========
+
+This page is a general overview of :ref:`libmaple proper
+<libmaple-vs-wirish>`. It describes libmaple's design, and names
+implementation patterns to look for when using it. General
+familiarity with the :ref:`STM32 <stm32>` is assumed; beginners should
+start with the high-level :ref:`Wirish interface <language>` instead.
+Examples are given from libmaple's sources.
+
+.. contents:: Contents
+ :local:
+
+Design Goals
+------------
+
+The central goal for libmaple proper is to provide a pleasant,
+portable, and consistent set of interfaces for dealing with the
+various series of STM32 microcontrollers.
+
+Portability in particular can be a problem when programming for the
+STM32. While the various STM32 series are largely pin-compatible with
+one another, the peripheral register maps between series often change
+drastically, even when the functionality provided by the peripheral
+doesn't change very much. This means that code which accesses
+registers directly often needs to change when porting a program to a
+different series MCU.
+
+ST's solution to this problem thus far has been to `issue
+<http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/FIRMWARE/stm32l1_stdperiph_lib.zip>`_
+`separate
+<http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/FIRMWARE/stm32f10x_stdperiph_lib.zip>`_
+`firmware
+<http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/FIRMWARE/stm32f2xx_stdperiph_lib.zip>`_
+`libraries
+<http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/FIRMWARE/stm32f4_dsp_stdperiph_lib.zip>`_;
+one for each STM32 series. Along with these, they have released a
+`number
+<http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/APPLICATION_NOTE/DM00024853.pdf>`_
+of `application
+<http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/APPLICATION_NOTE/DM00033267.pdf>`_
+`notes
+<http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/APPLICATION_NOTE/DM00032987.pdf>`_
+describing the compatibility issues and how to migrate between series
+by switching firmware libraries. Often, the migration advice is
+essentially "rewrite your code"; this occurs, for example, with any
+code involving GPIO or DMA being migrated between STM32F1 and STM32F2.
+
+Needless to say, this can be very annoying. (Didn't we solve this
+sort of problem years ago?) When you just want your robot to fly,
+your `LEDs to blink <http://www.youtube.com/watch?v=J845L45zqfk>`_, or
+your `FM synthesizer <https://github.com/Ixox/preen>`_ to, well,
+`synthesize <http://xhosxe.free.fr/IxoxFMSynth.mp3>`_, you probably
+couldn't care less about dealing with a new set of registers.
+
+We want to make it easier to write portable STM32 code. To enable
+that, libmaple abstracts away many hardware details behind portable
+interfaces. We also want to make it easy for you to get your hands
+dirty when need or desire arises. To that end, libmaple makes as few
+assumptions as possible, and does its best to get out of your way when
+you want it to leave.
+
+.. _libmaple-overview-devices:
+
+Libmaple's Device Model
+-----------------------
+
+The libmaple device model is simple and stupid. This is a feature.
+
+*Device types* are the central libmaple abstraction; they exist to
+provide portable interfaces to common peripherals, but they still let
+you do nonportable things easily if you want to.
+
+The rules for device types are:
+
+- Device types are structs representing peripherals. The name of the
+ device type for peripheral "foo" is ``struct foo_dev`` (so for
+ foo=ADC, it's ``struct adc_dev``. For foo=DMA, it's ``struct
+ dma_dev``; etc.). These are always ``typedef``\ ed to ``foo_dev``.
+
+- Each device type contains any information needed or used by libmaple
+ for operating on the peripheral the type represents. Device types
+ are defined alongside declarations for portable support routines in
+ the header ``<libmaple/foo.h>`` (examples: :ref:`libmaple-adc`,
+ :ref:`libmaple-dma`).
+
+- Direct :ref:`register access <libmaple-overview-regmaps>` is
+ possible via the ``regs`` field in each device type. (Given a
+ ``foo_dev *foo``, you can read and write the BAR register
+ ``FOO_BAR`` with ``foo->regs->BAR``.)
+
+- An :ref:`rcc_clk_id <libmaple-rcc-rcc_clk_id>` for the device is
+ available in the ``clk_id`` field; this is an opaque type that can
+ be used to uniquely identifies the peripheral. (Given ``foo_dev
+ *foo``, you can check which foo you have by looking at
+ ``foo->clk_id``.)
+
+- The backend for each supported STM32 series statically initializes
+ devices as appropriate, and ensures that the peripheral support
+ header includes declarations for pointers to these statically
+ allocated devices.
+
+- Peripheral support functions usually expect a pointer to a device as
+ their first argument. These functions' implementations may vary
+ with the particular microcontroller you're targeting, but their
+ semantics try to stay the same. To migrate to a different target,
+ you'll often be able to simply recompile your program (and libmaple)
+ for the new target.
+
+- When complete portability is not possible, libmaple tries to keep
+ the nonportable bits in data, rather than code.
+
+Example: ``adc_dev``
+~~~~~~~~~~~~~~~~~~~~
+
+These rules are best explained by example. The device type for ADC
+peripherals is ``struct adc_dev``. Its definition is provided by
+``<libmaple/adc.h>``::
+
+ typedef struct adc_dev {
+ adc_reg_map *regs;
+ rcc_clk_id clk_id;
+ } adc_dev;
+
+An ``adc_dev`` contains a pointer to its register map in the ``regs``
+field. This ``regs`` field is available on all device types. Its value
+is a :ref:`register map base pointer
+<libmaple-overview-regmaps-base-pts>` (like ``ADC1_BASE``, etc.) for
+the peripheral, as determined by the current target. For example, two
+equivalent expressions for reading the ADC1 regular data register are
+``ADC1_BASE->DR`` and ``ADC1->regs->DR`` (though the first one is
+faster). Manipulating registers directly via ``->regs`` is thus
+always possible, but can be nonportable, and should you choose to do
+this, it's up to you to get it right.
+
+An ``adc_dev`` also contains an ``rcc_clk_id`` for the ADC peripheral
+it represents in the ``clk_id`` field. The ``rcc_clk_id`` enum type
+has an enumerator for each peripheral supported by your series. For
+example, the ADC peripherals' ``rcc_clk_id`` enumerators are
+``RCC_ADC1``, ``RCC_ADC2``, and ``RCC_ADC3``. In general, an
+``rcc_clk_id`` is useful not only for managing the clock line to a
+peripheral, but also as a unique identifier for that peripheral.
+
+(Device types can be more complicated than this; ``adc_dev`` was
+chosen as a simple example of the minimum you can expect.)
+
+Rather than have you define your own ``adc_dev``\ s, libmaple defines
+them for you as appropriate for your target STM32 series. For example,
+on STM32F1, the file libmaple/stm32f1/adc.c contains the following::
+
+ 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;
+
+ #if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
+ static adc_dev adc3 = {
+ .regs = ADC3_BASE,
+ .clk_id = RCC_ADC3,
+ };
+ /** ADC3 device. */
+ const adc_dev *ADC3 = &adc3;
+ #endif
+
+Since all supported STM32F1 targets support ADC1 and ADC2, libmaple
+predefines corresponding ``adc_dev`` instances for you. To save space,
+it avoids defining an ``adc_dev`` for ADC3 unless you are targeting a
+high- or XL-density STM32F1, as medium- and lower density MCUs don't
+have ADC3.
+
+Note that the structs themselves are static and are exposed only via
+pointers. These pointers are declared in a series-specific ADC
+header, ``<series/adc.h>`` which is included by ``<libmaple/adc.h>``
+based on the MCU you're targeting. (**Never include <series/foo.h>
+directly**. Instead, include ``<libmaple/foo.h>`` and let it take
+care of that for you.) On STM32F1, the series ADC header contains the
+following::
+
+ extern const struct adc_dev *ADC1;
+ extern const struct adc_dev *ADC2;
+ #if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
+ extern const struct adc_dev *ADC3;
+ #endif
+
+In general, you access the predefined devices via these pointers. As
+illustrated by the ADC example, the variables for these pointers
+follow the naming scheme used in ST's reference manuals -- the pointer
+to ADC1's ``adc_dev`` is named ``ADC1``, and so on.
+
+The :ref:`API documentation <libmaple-apis>` for the peripherals
+you're interested in will list the available devices on each target.
+
+Using Devices
+~~~~~~~~~~~~~
+
+Peripheral support routines usually expect pointers to their device
+types as their first arguments. Here are some ADC examples::
+
+ uint16 adc_read(const adc_dev *dev, uint8 channel);
+ static inline void adc_enable(const adc_dev *dev);
+ static inline void adc_disable(const adc_dev *dev);
+
+So, to read channel 2 of ADC1, you could call ``adc_read(ADC1, 2)``.
+To disable ADC2, call ``adc_disable(ADC2)``; etc.
+
+That's it; there's nothing complicated here. In general, just follow
+links from the :ref:`libmaple-apis` page to the header for the
+peripheral you're interested in. It will explain the supported
+functionality, both portable and series-specific.
+
+Segregating Non-portable Functionality into Data
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As mentioned previously, when total portability isn't possible,
+libmaple tries to do the right thing and segregate the nonportable
+portions into data rather than code. The function
+``adc_set_sample_rate()`` is a good example of how this works, and why
+it's useful::
+
+ void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate);
+
+For example, while both STM32F1 and STM32F2 support setting the ADC
+sample time via the same register interface, the actual sample times
+supported are different. For instance, on STM32F1, available sample
+times include 1.5, 7.5, and 13.5 ADC cycles. On STM32F2, none of these
+are available, but 3, 15, and 28 ADC cycles are supported (which is
+not true for STM32F1). To work with this, libmaple provides a single
+function, ``adc_set_sample_rate()``, for setting an ADC controller's
+channel sampling time, but the actual sample rates it takes are given
+by the ``adc_smp_rate`` type, which is different on STM32F1 and
+STM32F2.
+
+This is the STM32F1 implementation of adc_smp_rate::
+
+ typedef enum adc_smp_rate {
+ ADC_SMPR_1_5, /**< 1.5 ADC cycles */
+ ADC_SMPR_7_5, /**< 7.5 ADC cycles */
+ ADC_SMPR_13_5, /**< 13.5 ADC cycles */
+ ADC_SMPR_28_5, /**< 28.5 ADC cycles */
+ ADC_SMPR_41_5, /**< 41.5 ADC cycles */
+ ADC_SMPR_55_5, /**< 55.5 ADC cycles */
+ ADC_SMPR_71_5, /**< 71.5 ADC cycles */
+ ADC_SMPR_239_5, /**< 239.5 ADC cycles */
+ } adc_smp_rate;
+
+And here is the STM32F2 implementation::
+
+ 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;
+
+So, on F1, you could call ``adc_set_sample_rate(ADC1, ADC_SMPR_1_5)``,
+and on F2, you could call ``adc_set_sample_rate(ADC1,
+ADC_SMPR_3)``. If you're only interested in one of those series, then
+that's all you need to know.
+
+However, if you're targeting multiple series, then this is useful
+because it lets you put the actual sample time for the MCU you're
+targeting into a variable (or macro, etc.), whose value depends on the
+target you're compiling for. This lets you have a single codebase to
+test and maintain, and lets you add support for a new target by simply
+adding some new data.
+
+To continue the example, one easy way is to pick an ``adc_smp_rate``
+for each of STM32F1 and STM32F2 is with conditional compilation. Using
+the :ref:`STM32_MCU_SERIES <libmaple-stm32-STM32_MCU_SERIES>` define
+from :ref:`libmaple-stm32`, you can write::
+
+ #include <libmaple/adc.h>
+ #include <libmaple/stm32.h>
+
+ #if STM32_MCU_SERIES == STM32_SERIES_F1
+ /* Target is an STM32F1 */
+ adc_smp_rate smp_rate = ADC_SMPR_1_5;
+ #elif STM32_MCU_SERIES == STM32_SERIES_F2
+ /* Target is an STM32F2 */
+ adc_smp_rate smp_rate = ADC_SMPR_3;
+ #else
+ #error "Unsupported STM32 target; can't pick a sample rate"
+ #endif
+
+ void setup(void) {
+ adc_set_smp_rate(ADC1, smp_rate);
+ }
+
+Adding support for e.g. STM32F4 would only require adding a new
+``#elif`` for that series. This is simple, but hackish, and can get
+out of control if you're not careful.
+
+Another way to get the job done is to declare an ``extern adc_smp_rate
+smp_rate``, and use the build system to compile a file defining
+``smp_rate`` depending on your target. As was discussed earlier, this
+is what libmaple does when choosing which files to use for defining
+the appropriate ``adc_dev``\ s for your target. How to do this is
+outside the scope of this overview, however.
+
+.. _libmaple-overview-regmaps:
+
+Register Maps
+-------------
+
+Though we aim to enable libmaple's users to interact with the more
+portable :ref:`device interface <libmaple-overview-devices>` as much
+as possible, there will always be a need for efficient direct register
+access. To allow for that, libmaple provides *register maps* as a
+consistent set of names and abstractions for dealing with peripheral
+registers and their bits.
+
+A *register map type* is a struct which names and provides access to a
+peripheral's registers (we can use a struct because registers are
+usually mapped into contiguous regions of memory). Here's an example
+register map for the DAC peripheral on STM32F1 series MCUs (``__io``
+is just libmaple's way of saying ``volatile`` when referring to
+register values)::
+
+ 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 */
+ } dac_reg_map;
+
+There are two things to notice here. First, if the chip reference
+manual (for STM32F1, that's RM0008) names a register ``DAC_FOO``, then
+``dac_reg_map`` has a field named ``FOO``. So, the Channel 1 12-bit
+right-aligned data register (DAC_DHR12R1) is the ``DHR12R1`` field in
+a ``dac_reg_map``. Second, if the reference manual describes a
+register as "Foo bar register", the documentation for the
+corresponding field has the same description. This consistency makes
+it easy to search for a particular register, and, if you see one used
+in a source file, to feel sure about what's going on just based on its
+name.
+
+.. _libmaple-overview-regmaps-base-pts:
+
+So let's say you've included ``<libmaple/foo.h>``, and you want to
+mess with some particular register. You'll do this using *register map
+base pointers*, which are pointers to ``struct foo_reg_map``. What's
+the name of the base pointer you want? That depends on if there's
+more than one foo or not. If there's only one foo, then libmaple
+guarantees there will be a ``#define`` that looks like like this::
+
+ #define FOO_BASE ((struct foo_reg_map*)0xDEADBEEF)
+
+That is, you're guaranteed there will be a pointer to the (only)
+``foo_reg_map`` you want, and it will be called
+``FOO_BASE``. (``0xDEADBEEF`` is the register map's *base address*, or
+the fixed location in memory where the register map begins). Here's
+an example for STM32F1::
+
+ #define DAC_BASE ((struct dac_reg_map*)0x40007400)
+
+Here are some examples for how to read and write to registers using
+register map base pointers.
+
+* In order to write 2048 to the channel 1 12-bit left-aligned data
+ holding register (DAC_DHR12L1), you would write::
+
+ DAC_BASE->DHR12L1 = 2048;
+
+* In order to read the DAC control register, you would write::
+
+ uint32 cr = DAC_BASE->CR;
+
+That covers the case where there's a single foo peripheral. If
+there's more than one (say, if there are *n*), then
+``<libmaple/foo.h>`` provides the following::
+
+ #define FOO1_BASE ((struct foo_reg_map*)0xDEADBEEF)
+ #define FOO2_BASE ((struct foo_reg_map*)0xF00DF00D)
+ ...
+ #define FOOn_BASE ((struct foo_reg_map*)0x1EAF1AB5)
+
+Here are some examples for the ADCs on STM32F1::
+
+ #define ADC1_BASE ((struct adc_reg_map*)0x40012400)
+ #define ADC2_BASE ((struct adc_reg_map*)0x40012800)
+
+In order to read from the ADC1's regular data register (where the
+results of ADC conversion are stored), you would write::
+
+ uint32 converted_result = ADC1_BASE->DR;
+
+Register Bit Definitions
+------------------------
+
+In ``<libmaple/foo.h>``, there will also be a variety of ``#define``\
+s for dealing with interesting bits in the xxx registers, called
+*register bit definitions*. In keeping with the ST reference manuals,
+these are named according to the scheme ``FOO_REG_FIELD``, where
+"``REG``" refers to the register, and "``FIELD``" refers to the bit or
+bits in ``REG`` that are special.
+
+Again, this is probably best explained by example. On STM32F1, each
+Direct Memory Access (DMA) controller's register map has a certain
+number of channel configuration registers (DMA_CCRx). In each of
+these channel configuration registers, bit 14 is called the
+``MEM2MEM`` bit, and bits 13 and 12 are the priority level (``PL``)
+bits. Here are the register bit definitions for those fields on
+STM32F1::
+
+ #define DMA_CCR_MEM2MEM_BIT 14
+ #define DMA_CCR_MEM2MEM (1U << DMA_CCR_MEM2MEM_BIT)
+ #define DMA_CCR_PL (0x3 << 12)
+ #define DMA_CCR_PL_LOW (0x0 << 12)
+ #define DMA_CCR_PL_MEDIUM (0x1 << 12)
+ #define DMA_CCR_PL_HIGH (0x2 << 12)
+ #define DMA_CCR_PL_VERY_HIGH (0x3 << 12)
+
+Thus, to check if the ``MEM2MEM`` bit is set in DMA controller 1's
+channel configuration register 2 (DMA_CCR2), you can write::
+
+ if (DMA1_BASE->CCR2 & DMA_CCR_MEM2MEM) {
+ /* MEM2MEM is set */
+ }
+
+Certain register values occupy multiple bits. For example, the
+priority level (PL) of a DMA channel is determined by bits 13 and 12
+of the corresponding channel configuration register. As shown above,
+libmaple provides several register bit definitions for masking out the
+individual PL bits and determining their meaning. For example, to set
+the priority level of a DMA transfer to "high priority", you can
+do a read-modify-write sequence on the DMA_CCR_PL bits like so::
+
+ uint32 ccr = DMA1_BASE->CCR2;
+ ccr &= ~DMA_CCR_PL;
+ ccr |= DMA_CCR_PL_HIGH;
+ DMA1_BASE->CCR2 = ccr;
+
+Of course, before doing that, you should check to make sure there's
+not already a device-level function for performing the same task! (In
+this case, there is. It's called :c:func:`dma_set_priority()`; see
+:ref:`libmaple-dma`.) For instance, **none of the above code is
+portable** to STM32F4, which uses DMA streams instead of channels for
+this purpose.
+
+Peripheral Support Routines
+---------------------------
+
+This section describes patterns to look for in peripheral support
+routines.
+
+In general, each device needs to be initialized before it can be used.
+libmaple provides this initialization routine for each peripheral
+``foo``; its name is ``foo_init()``. These initialization routines
+turn on the clock to a device, and restore its register values to
+their default settings. Here are a few examples::
+
+ /* From <libmaple/dma.h> */
+ void dma_init(dma_dev *dev);
+
+ /* From <libmaple/gpio.h> */
+ void gpio_init(gpio_dev *dev);
+ void gpio_init_all(void);
+
+Note that, sometimes, there will be an additional initialization
+routine for all available peripherals of a certain kind.
+
+Many peripherals also need additional configuration before they can be
+used. These functions are usually called something along the lines of
+``foo_enable()``, and often take additional arguments which specify a
+particular configuration for the peripheral. Some examples::
+
+ /* From <libmaple/usart.h> */
+ void usart_enable(usart_dev *dev);
+
+ /* From <libmaple/i2c.h> */
+ void i2c_master_enable(i2c_dev *dev, uint32 flags);
+
+After you've initialized, and potentially enabled, your peripheral, it
+is now time to begin using it. The :ref:`libmaple API pages
+<libmaple-apis>` are your friends here.
+
+.. rubric:: Footnotes
+
+.. [#fgpio] As an exception, GPIO ports are given letters instead of
+ numbers (``GPIOA`` and ``GPIOB`` instead of ``GPIO1`` and
+ ``GPIO2``, etc.).