aboutsummaryrefslogtreecommitdiffstats
path: root/source/libmaple
diff options
context:
space:
mode:
Diffstat (limited to 'source/libmaple')
-rw-r--r--source/libmaple/api/adc.rst360
-rw-r--r--source/libmaple/api/bitband.rst4
-rw-r--r--source/libmaple/api/delay.rst11
-rw-r--r--source/libmaple/api/flash.rst296
-rw-r--r--source/libmaple/api/fsmc.rst348
-rw-r--r--source/libmaple/api/iwdg.rst79
-rw-r--r--source/libmaple/api/libmaple.rst4
-rw-r--r--source/libmaple/api/libmaple_types.rst68
-rw-r--r--source/libmaple/api/nvic.rst43
-rw-r--r--source/libmaple/api/rcc-reg-bits.txt1017
-rw-r--r--source/libmaple/api/rcc.rst677
-rw-r--r--source/libmaple/api/ring_buffer.rst4
-rw-r--r--source/libmaple/api/stm32.rst118
-rw-r--r--source/libmaple/api/usart.rst1
-rw-r--r--source/libmaple/api/util.rst19
-rw-r--r--source/libmaple/apis.rst4
-rw-r--r--source/libmaple/overview.rst642
17 files changed, 2628 insertions, 1067 deletions
diff --git a/source/libmaple/api/adc.rst b/source/libmaple/api/adc.rst
index fecaece..2f06926 100644
--- a/source/libmaple/api/adc.rst
+++ b/source/libmaple/api/adc.rst
@@ -1,24 +1,31 @@
.. highlight:: c
.. _libmaple-adc:
-``adc.h``
-=========
+``<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
-Types
------
+Devices
+-------
+
+The individual ADC peripherals have the following device struct.
.. doxygenstruct:: adc_dev
-.. doxygenstruct:: adc_reg_map
-.. doxygenenum:: adc_extsel_event
-.. doxygenenum:: adc_smp_rate
-Devices
--------
+The available ADC peripherals vary by target. The complete list is
+``ADC1``, ``ADC2``, and ``ADC3``.
.. doxygenvariable:: ADC1
.. doxygenvariable:: ADC2
@@ -27,189 +34,198 @@ Devices
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
-.. doxygenfunction:: adc_calibrate
-.. doxygenfunction:: adc_set_extsel
+.. _adc-adc_enable:
.. doxygenfunction:: adc_enable
+.. _adc-adc_disable:
.. doxygenfunction:: adc_disable
+.. _adc-adc_disable_all:
.. doxygenfunction:: adc_disable_all
-.. doxygenfunction:: adc_foreach
-.. doxygenfunction:: adc_set_sample_rate
+
+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
-.. doxygenfunction:: adc_set_exttrig
+.. _adc-adc_set_extsel:
+.. doxygenfunction:: adc_set_extsel
-Register Map Base Pointers
---------------------------
+.. _adc-adc_extsel_event:
-.. doxygendefine:: ADC1_BASE
-.. doxygendefine:: ADC2_BASE
-.. doxygendefine:: ADC3_BASE
+The last of these, :ref:`adc_set_extsel() <adc-adc_set_extsel>`, takes
+a target-dependent ``adc_extsel_event`` argument.
-Register Bit Definitions
-------------------------
+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
-Status register
+.. _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
~~~~~~~~~~~~~~~
-.. doxygendefine:: ADC_SR_AWD_BIT
-.. doxygendefine:: ADC_SR_EOC_BIT
-.. doxygendefine:: ADC_SR_JEOC_BIT
-.. doxygendefine:: ADC_SR_JSTRT_BIT
-.. doxygendefine:: ADC_SR_STRT_BIT
-
-.. doxygendefine:: ADC_SR_AWD
-.. doxygendefine:: ADC_SR_EOC
-.. doxygendefine:: ADC_SR_JEOC
-.. doxygendefine:: ADC_SR_JSTRT
-.. doxygendefine:: ADC_SR_STRT
-
-Control register 1
-~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: ADC_CR1_EOCIE_BIT
-.. doxygendefine:: ADC_CR1_AWDIE_BIT
-.. doxygendefine:: ADC_CR1_JEOCIE_BIT
-.. doxygendefine:: ADC_CR1_SCAN_BIT
-.. doxygendefine:: ADC_CR1_AWDSGL_BIT
-.. doxygendefine:: ADC_CR1_JAUTO_BIT
-.. doxygendefine:: ADC_CR1_DISCEN_BIT
-.. doxygendefine:: ADC_CR1_JDISCEN_BIT
-.. doxygendefine:: ADC_CR1_JAWDEN_BIT
-.. doxygendefine:: ADC_CR1_AWDEN_BIT
-
-.. doxygendefine:: ADC_CR1_AWDCH
-.. doxygendefine:: ADC_CR1_EOCIE
-.. doxygendefine:: ADC_CR1_AWDIE
-.. doxygendefine:: ADC_CR1_JEOCIE
-.. doxygendefine:: ADC_CR1_SCAN
-.. doxygendefine:: ADC_CR1_AWDSGL
-.. doxygendefine:: ADC_CR1_JAUTO
-.. doxygendefine:: ADC_CR1_DISCEN
-.. doxygendefine:: ADC_CR1_JDISCEN
-.. doxygendefine:: ADC_CR1_DISCNUM
-.. doxygendefine:: ADC_CR1_JAWDEN
-.. doxygendefine:: ADC_CR1_AWDEN
-
-Control register 2
-~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: ADC_CR2_ADON_BIT
-.. doxygendefine:: ADC_CR2_CONT_BIT
-.. doxygendefine:: ADC_CR2_CAL_BIT
-.. doxygendefine:: ADC_CR2_RSTCAL_BIT
-.. doxygendefine:: ADC_CR2_DMA_BIT
-.. doxygendefine:: ADC_CR2_ALIGN_BIT
-.. doxygendefine:: ADC_CR2_JEXTTRIG_BIT
-.. doxygendefine:: ADC_CR2_EXTTRIG_BIT
-.. doxygendefine:: ADC_CR2_JSWSTART_BIT
-.. doxygendefine:: ADC_CR2_SWSTART_BIT
-.. doxygendefine:: ADC_CR2_TSEREFE_BIT
-
-.. doxygendefine:: ADC_CR2_ADON
-.. doxygendefine:: ADC_CR2_CONT
-.. doxygendefine:: ADC_CR2_CAL
-.. doxygendefine:: ADC_CR2_RSTCAL
-.. doxygendefine:: ADC_CR2_DMA
-.. doxygendefine:: ADC_CR2_ALIGN
-.. doxygendefine:: ADC_CR2_JEXTSEL
-.. doxygendefine:: ADC_CR2_JEXTTRIG
-.. doxygendefine:: ADC_CR2_EXTSEL
-.. doxygendefine:: ADC_CR2_EXTTRIG
-.. doxygendefine:: ADC_CR2_JSWSTART
-.. doxygendefine:: ADC_CR2_SWSTART
-.. doxygendefine:: ADC_CR2_TSEREFE
-
-Sample time register 1
-~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: ADC_SMPR1_SMP17
-.. doxygendefine:: ADC_SMPR1_SMP16
-.. doxygendefine:: ADC_SMPR1_SMP15
-.. doxygendefine:: ADC_SMPR1_SMP14
-.. doxygendefine:: ADC_SMPR1_SMP13
-.. doxygendefine:: ADC_SMPR1_SMP12
-.. doxygendefine:: ADC_SMPR1_SMP11
-.. doxygendefine:: ADC_SMPR1_SMP10
-
-Sample time register 2
-~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: ADC_SMPR2_SMP9
-.. doxygendefine:: ADC_SMPR2_SMP8
-.. doxygendefine:: ADC_SMPR2_SMP7
-.. doxygendefine:: ADC_SMPR2_SMP6
-.. doxygendefine:: ADC_SMPR2_SMP5
-.. doxygendefine:: ADC_SMPR2_SMP4
-.. doxygendefine:: ADC_SMPR2_SMP3
-.. doxygendefine:: ADC_SMPR2_SMP2
-.. doxygendefine:: ADC_SMPR2_SMP1
-.. doxygendefine:: ADC_SMPR2_SMP0
-
-Injected channel data offset register
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: ADC_JOFR_JOFFSET
-
-Watchdog high threshold register
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: ADC_HTR_HT
-
-Watchdog low threshold register
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: ADC_LTR_LT
-
-Regular sequence register 1
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+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.
-.. doxygendefine:: ADC_SQR1_L
-.. doxygendefine:: ADC_SQR1_SQ16
-.. doxygendefine:: ADC_SQR1_SQ15
-.. doxygendefine:: ADC_SQR1_SQ14
-.. doxygendefine:: ADC_SQR1_SQ13
+.. 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.
-Regular sequence register 2
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. 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.
-.. doxygendefine:: ADC_SQR2_SQ12
-.. doxygendefine:: ADC_SQR2_SQ11
-.. doxygendefine:: ADC_SQR2_SQ10
-.. doxygendefine:: ADC_SQR2_SQ9
-.. doxygendefine:: ADC_SQR2_SQ8
-.. doxygendefine:: ADC_SQR2_SQ7
+.. doxygenfunction:: adc_set_sample_rate
-Regular sequence register 3
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. _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
+~~~~~~~~~~~~~
-.. doxygendefine:: ADC_SQR3_SQ6
-.. doxygendefine:: ADC_SQR3_SQ5
-.. doxygendefine:: ADC_SQR3_SQ4
-.. doxygendefine:: ADC_SQR3_SQ3
-.. doxygendefine:: ADC_SQR3_SQ2
-.. doxygendefine:: ADC_SQR3_SQ1
+.. FIXME [0.0.13] why don't adc_config_gpio()'s docs show up?
-Injected sequence register
-~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. _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
-.. doxygendefine:: ADC_JSQR_JL
-.. doxygendefine:: ADC_JSQR_JL_1CONV
-.. doxygendefine:: ADC_JSQR_JL_2CONV
-.. doxygendefine:: ADC_JSQR_JL_3CONV
-.. doxygendefine:: ADC_JSQR_JL_4CONV
-.. doxygendefine:: ADC_JSQR_JSQ4
-.. doxygendefine:: ADC_JSQR_JSQ3
-.. doxygendefine:: ADC_JSQR_JSQ2
-.. doxygendefine:: ADC_JSQR_JSQ1
+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
+------------------------
-Injected data registers
-~~~~~~~~~~~~~~~~~~~~~~~
+.. TODO [0.0.13]
-.. doxygendefine:: ADC_JDR_JDATA
+TODO
-Regular data register
-~~~~~~~~~~~~~~~~~~~~~
+.. rubric:: Footnotes
-.. doxygendefine:: ADC_DR_ADC2DATA
-.. doxygendefine:: ADC_DR_DATA
+.. [#fchansamp] Per-channel sample time configuration is possible,
+ but currently unsupported.
diff --git a/source/libmaple/api/bitband.rst b/source/libmaple/api/bitband.rst
index 5251015..768f678 100644
--- a/source/libmaple/api/bitband.rst
+++ b/source/libmaple/api/bitband.rst
@@ -1,8 +1,8 @@
.. highlight:: c
.. _libmaple-bitband:
-``bitband.h``
-=============
+``<libmaple/bitband.h>``
+========================
Bit-banding support.
diff --git a/source/libmaple/api/delay.rst b/source/libmaple/api/delay.rst
index 5d0397d..d11496b 100644
--- a/source/libmaple/api/delay.rst
+++ b/source/libmaple/api/delay.rst
@@ -1,12 +1,11 @@
.. highlight:: c
.. _libmaple-delay:
-``delay.h``
-===========
+``<libmaple/delay.h>``
+======================
-Simple busy-loop delaying.
-
-Functions
----------
+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/source/libmaple/api/flash.rst b/source/libmaple/api/flash.rst
index 8a7e79b..52ff4d2 100644
--- a/source/libmaple/api/flash.rst
+++ b/source/libmaple/api/flash.rst
@@ -1,97 +1,249 @@
.. highlight:: c
.. _libmaple-flash:
-``flash.h``
-===========
+``<libmaple/flash.h>``
+======================
-Flash support.
+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:
-Types
------
+Devices
+-------
-.. doxygenstruct:: flash_reg_map
+None at this time.
Functions
---------
-.. doxygenfunction:: flash_enable_prefetch
+The following functions can be used to portably manipulate Flash memory.
+
.. doxygenfunction:: flash_set_latency
+.. doxygenfunction:: flash_enable_features
+.. doxygenfunction:: flash_enable_prefetch
-Register Map Base Pointers
---------------------------
+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
------------------------
-Access control register
-~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: FLASH_ACR_PRFTBS_BIT
-.. doxygendefine:: FLASH_ACR_PRFTBE_BIT
-.. doxygendefine:: FLASH_ACR_HLFCYA_BIT
+These are given as source code. Available register bit definitions
+vary by target.
-.. doxygendefine:: FLASH_ACR_PRFTBS
-.. doxygendefine:: FLASH_ACR_PRFTBE
-.. doxygendefine:: FLASH_ACR_HLFCYA
-.. doxygendefine:: FLASH_ACR_LATENCY
+STM32F1 Targets
+~~~~~~~~~~~~~~~
-Status register
+::
+
+ /* 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
~~~~~~~~~~~~~~~
-.. doxygendefine:: FLASH_SR_EOP_BIT
-.. doxygendefine:: FLASH_SR_WRPRTERR_BIT
-.. doxygendefine:: FLASH_SR_PGERR_BIT
-.. doxygendefine:: FLASH_SR_BSY_BIT
-
-.. doxygendefine:: FLASH_SR_EOP
-.. doxygendefine:: FLASH_SR_WRPRTERR
-.. doxygendefine:: FLASH_SR_PGERR
-.. doxygendefine:: FLASH_SR_BSY
-
-Control register
-~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: FLASH_CR_EOPIE_BIT
-.. doxygendefine:: FLASH_CR_ERRIE_BIT
-.. doxygendefine:: FLASH_CR_OPTWRE_BIT
-.. doxygendefine:: FLASH_CR_LOCK_BIT
-.. doxygendefine:: FLASH_CR_STRT_BIT
-.. doxygendefine:: FLASH_CR_OPTER_BIT
-.. doxygendefine:: FLASH_CR_OPTPG_BIT
-.. doxygendefine:: FLASH_CR_MER_BIT
-.. doxygendefine:: FLASH_CR_PER_BIT
-.. doxygendefine:: FLASH_CR_PG_BIT
-
-.. doxygendefine:: FLASH_CR_EOPIE
-.. doxygendefine:: FLASH_CR_ERRIE
-.. doxygendefine:: FLASH_CR_OPTWRE
-.. doxygendefine:: FLASH_CR_LOCK
-.. doxygendefine:: FLASH_CR_STRT
-.. doxygendefine:: FLASH_CR_OPTER
-.. doxygendefine:: FLASH_CR_OPTPG
-.. doxygendefine:: FLASH_CR_MER
-.. doxygendefine:: FLASH_CR_PER
-.. doxygendefine:: FLASH_CR_PG
-
-Option byte register
-~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: FLASH_OBR_nRST_STDBY_BIT
-.. doxygendefine:: FLASH_OBR_nRST_STOP_BIT
-.. doxygendefine:: FLASH_OBR_WDG_SW_BIT
-.. doxygendefine:: FLASH_OBR_RDPRT_BIT
-.. doxygendefine:: FLASH_OBR_OPTERR_BIT
-
-.. doxygendefine:: FLASH_OBR_DATA1
-.. doxygendefine:: FLASH_OBR_DATA0
-.. doxygendefine:: FLASH_OBR_USER
-.. doxygendefine:: FLASH_OBR_nRST_STDBY
-.. doxygendefine:: FLASH_OBR_nRST_STOP
-.. doxygendefine:: FLASH_OBR_WDG_SW
-.. doxygendefine:: FLASH_OBR_RDPRT
-.. doxygendefine:: FLASH_OBR_OPTERR
+::
+
+ /* 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/source/libmaple/api/fsmc.rst b/source/libmaple/api/fsmc.rst
index 3b356cc..e2bf87a 100644
--- a/source/libmaple/api/fsmc.rst
+++ b/source/libmaple/api/fsmc.rst
@@ -1,19 +1,43 @@
.. highlight:: c
.. _libmaple-fsmc:
-``fsmc.h``
-==========
+``<libmaple/fsmc.h>``
+=====================
-Flexible Static Memory Controller (FSMC) support.
+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:
-Types
------
+Usage Note
+----------
-.. doxygenstruct:: fsmc_reg_map
-.. doxygenstruct:: fsmc_nor_psram_reg_map
+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
-------
@@ -23,13 +47,49 @@ 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
@@ -40,150 +100,136 @@ Memory Bank Boundary Addresses
.. doxygendefine:: FSMC_NOR_PSRAM_REGION3
.. doxygendefine:: FSMC_NOR_PSRAM_REGION4
-Register Map Base Pointers
---------------------------
-
-.. doxygendefine:: FSMC_BASE
-
-.. doxygendefine:: FSMC_NOR_PSRAM1_BASE
-.. doxygendefine:: FSMC_NOR_PSRAM2_BASE
-.. doxygendefine:: FSMC_NOR_PSRAM3_BASE
-.. doxygendefine:: FSMC_NOR_PSRAM4_BASE
-
Register Bit Definitions
------------------------
-NOR/PSRAM Chip-Select Control Registers
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: FSMC_BCR_CBURSTRW_BIT
-.. doxygendefine:: FSMC_BCR_ASYNCWAIT_BIT
-.. doxygendefine:: FSMC_BCR_EXTMOD_BIT
-.. doxygendefine:: FSMC_BCR_WAITEN_BIT
-.. doxygendefine:: FSMC_BCR_WREN_BIT
-.. doxygendefine:: FSMC_BCR_WAITCFG_BIT
-.. doxygendefine:: FSMC_BCR_WRAPMOD_BIT
-.. doxygendefine:: FSMC_BCR_WAITPOL_BIT
-.. doxygendefine:: FSMC_BCR_BURSTEN_BIT
-.. doxygendefine:: FSMC_BCR_FACCEN_BIT
-.. doxygendefine:: FSMC_BCR_MUXEN_BIT
-.. doxygendefine:: FSMC_BCR_MBKEN_BIT
-
-.. doxygendefine:: FSMC_BCR_CBURSTRW
-.. doxygendefine:: FSMC_BCR_ASYNCWAIT
-.. doxygendefine:: FSMC_BCR_EXTMOD
-.. doxygendefine:: FSMC_BCR_WAITEN
-.. doxygendefine:: FSMC_BCR_WREN
-.. doxygendefine:: FSMC_BCR_WAITCFG
-.. doxygendefine:: FSMC_BCR_WRAPMOD
-.. doxygendefine:: FSMC_BCR_WAITPOL
-.. doxygendefine:: FSMC_BCR_BURSTEN
-.. doxygendefine:: FSMC_BCR_FACCEN
-.. doxygendefine:: FSMC_BCR_MWID
-.. doxygendefine:: FSMC_BCR_MWID_8BITS
-.. doxygendefine:: FSMC_BCR_MWID_16BITS
-.. doxygendefine:: FSMC_BCR_MTYP
-.. doxygendefine:: FSMC_BCR_MTYP_SRAM
-.. doxygendefine:: FSMC_BCR_MTYP_PSRAM
-.. doxygendefine:: FSMC_BCR_MTYP_NOR_FLASH
-.. doxygendefine:: FSMC_BCR_MUXEN
-.. doxygendefine:: FSMC_BCR_MBKEN
-
-SRAM/NOR-Flash Chip-Select Timing Registers
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: FSMC_BTR_ACCMOD
-.. doxygendefine:: FSMC_BTR_ACCMOD_A
-.. doxygendefine:: FSMC_BTR_ACCMOD_B
-.. doxygendefine:: FSMC_BTR_ACCMOD_C
-.. doxygendefine:: FSMC_BTR_ACCMOD_D
-.. doxygendefine:: FSMC_BTR_DATLAT
-.. doxygendefine:: FSMC_BTR_CLKDIV
-.. doxygendefine:: FSMC_BTR_BUSTURN
-.. doxygendefine:: FSMC_BTR_DATAST
-.. doxygendefine:: FSMC_BTR_ADDHLD
-.. doxygendefine:: FSMC_BTR_ADDSET
-
-SRAM/NOR-Flash Write Timing Registers
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: FSMC_BWTR_ACCMOD
-.. doxygendefine:: FSMC_BWTR_ACCMOD_A
-.. doxygendefine:: FSMC_BWTR_ACCMOD_B
-.. doxygendefine:: FSMC_BWTR_ACCMOD_C
-.. doxygendefine:: FSMC_BWTR_ACCMOD_D
-.. doxygendefine:: FSMC_BWTR_DATLAT
-.. doxygendefine:: FSMC_BWTR_CLKDIV
-.. doxygendefine:: FSMC_BWTR_DATAST
-.. doxygendefine:: FSMC_BWTR_ADDHLD
-.. doxygendefine:: FSMC_BWTR_ADDSET
-
-NAND Flash/PC Card Controller Registers
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: FSMC_PCR_ECCEN_BIT
-.. doxygendefine:: FSMC_PCR_PTYP_BIT
-.. doxygendefine:: FSMC_PCR_PBKEN_BIT
-.. doxygendefine:: FSMC_PCR_PWAITEN_BIT
-
-.. doxygendefine:: FSMC_PCR_ECCPS
-.. doxygendefine:: FSMC_PCR_ECCPS_256B
-.. doxygendefine:: FSMC_PCR_ECCPS_512B
-.. doxygendefine:: FSMC_PCR_ECCPS_1024B
-.. doxygendefine:: FSMC_PCR_ECCPS_2048B
-.. doxygendefine:: FSMC_PCR_ECCPS_4096B
-.. doxygendefine:: FSMC_PCR_ECCPS_8192B
-.. doxygendefine:: FSMC_PCR_TAR
-.. doxygendefine:: FSMC_PCR_TCLR
-.. doxygendefine:: FSMC_PCR_ECCEN
-.. doxygendefine:: FSMC_PCR_PWID
-.. doxygendefine:: FSMC_PCR_PWID_8BITS
-.. doxygendefine:: FSMC_PCR_PWID_16BITS
-.. doxygendefine:: FSMC_PCR_PTYP
-.. doxygendefine:: FSMC_PCR_PTYP_PC_CF_PCMCIA
-.. doxygendefine:: FSMC_PCR_PTYP_NAND
-.. doxygendefine:: FSMC_PCR_PBKEN
-.. doxygendefine:: FSMC_PCR_PWAITEN
-
-FIFO Status And Interrupt Registers
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: FSMC_SR_FEMPT_BIT
-.. doxygendefine:: FSMC_SR_IFEN_BIT
-.. doxygendefine:: FSMC_SR_ILEN_BIT
-.. doxygendefine:: FSMC_SR_IREN_BIT
-.. doxygendefine:: FSMC_SR_IFS_BIT
-.. doxygendefine:: FSMC_SR_ILS_BIT
-.. doxygendefine:: FSMC_SR_IRS_BIT
-
-.. doxygendefine:: FSMC_SR_FEMPT
-.. doxygendefine:: FSMC_SR_IFEN
-.. doxygendefine:: FSMC_SR_ILEN
-.. doxygendefine:: FSMC_SR_IREN
-.. doxygendefine:: FSMC_SR_IFS
-.. doxygendefine:: FSMC_SR_ILS
-.. doxygendefine:: FSMC_SR_IRS
-
-Common Memory Space Timing Registers
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: FSMC_PMEM_MEMHIZ
-.. doxygendefine:: FSMC_PMEM_MEMHOLD
-.. doxygendefine:: FSMC_PMEM_MEMWAIT
-.. doxygendefine:: FSMC_PMEM_MEMSET
-
-Attribute Memory Space Timing Registers
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: FSMC_PATT_ATTHIZ
-.. doxygendefine:: FSMC_PATT_ATTHOLD
-.. doxygendefine:: FSMC_PATT_ATTWAIT
-.. doxygendefine:: FSMC_PATT_ATTSET
-
-I/O Space Timing Register 4
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: FSMC_PIO_IOHIZ
-.. doxygendefine:: FSMC_PIO_IOHOLD
-.. doxygendefine:: FSMC_PIO_IOWAIT
-.. doxygendefine:: FSMC_PIO_IOSET
+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/source/libmaple/api/iwdg.rst b/source/libmaple/api/iwdg.rst
index 06691f8..65f9f7b 100644
--- a/source/libmaple/api/iwdg.rst
+++ b/source/libmaple/api/iwdg.rst
@@ -1,10 +1,11 @@
.. highlight:: c
.. _libmaple-iwdg:
-``iwdg.h``
-==========
+``<libmaple/iwdg.h>``
+=====================
-Independent Watchdog (IWDG) support.
+Independent Watchdog (IWDG) support. The IWDG peripheral is common
+across supported targets, so everything documented here is portable.
.. contents:: Contents
:local:
@@ -12,20 +13,15 @@ Independent Watchdog (IWDG) support.
Usage Note
----------
-To use the independent watchdog, first call :c:func:`iwdg_init()` with
-the appropriate prescaler and IWDG counter reload values for your
-application. Afterwards, you must periodically call
-:c:func:`iwdg_feed()` before the IWDG counter reaches 0 to reset the
-counter to its reload value. If you do not, the chip will reset.
+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.
-Types
------
-
-.. doxygenstruct:: iwdg_reg_map
-.. doxygenenum:: iwdg_prescaler
-
Devices
-------
@@ -34,40 +30,51 @@ None at this time.
Functions
---------
+.. _libmaple-iwdg-iwdg_init:
.. doxygenfunction:: iwdg_init
+.. _libmaple-iwdg-iwdg_feed:
.. doxygenfunction:: iwdg_feed
-Register Map Base Pointers
---------------------------
+Types
+-----
+
+.. doxygenenum:: iwdg_prescaler
+
+
+Register Maps
+-------------
.. doxygendefine:: IWDG_BASE
+.. doxygenstruct:: iwdg_reg_map
+
Register Bit Definitions
------------------------
-Key register
-~~~~~~~~~~~~
+These are given as source code.
+
+::
+
+ /* Key register */
-.. doxygendefine:: IWDG_KR_UNLOCK
-.. doxygendefine:: IWDG_KR_FEED
-.. doxygendefine:: IWDG_KR_START
+ #define IWDG_KR_UNLOCK 0x5555
+ #define IWDG_KR_FEED 0xAAAA
+ #define IWDG_KR_START 0xCCCC
-Prescaler register
-~~~~~~~~~~~~~~~~~~
+ /* Prescaler register */
-.. doxygendefine:: IWDG_PR_DIV_4
-.. doxygendefine:: IWDG_PR_DIV_8
-.. doxygendefine:: IWDG_PR_DIV_16
-.. doxygendefine:: IWDG_PR_DIV_32
-.. doxygendefine:: IWDG_PR_DIV_64
-.. doxygendefine:: IWDG_PR_DIV_128
-.. doxygendefine:: IWDG_PR_DIV_256
+ #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
-~~~~~~~~~~~~~~~
+ /* Status register */
-.. doxygendefine:: IWDG_SR_RVU_BIT
-.. doxygendefine:: IWDG_SR_PVU_BIT
+ #define IWDG_SR_RVU_BIT 1
+ #define IWDG_SR_PVU_BIT 0
-.. doxygendefine:: IWDG_SR_RVU
-.. doxygendefine:: IWDG_SR_PVU
+ #define IWDG_SR_RVU (1U << IWDG_SR_RVU_BIT)
+ #define IWDG_SR_PVU (1U << IWDG_SR_PVU_BIT)
diff --git a/source/libmaple/api/libmaple.rst b/source/libmaple/api/libmaple.rst
index c230cef..7deb659 100644
--- a/source/libmaple/api/libmaple.rst
+++ b/source/libmaple/api/libmaple.rst
@@ -1,8 +1,8 @@
.. highlight:: c
.. _libmaple-libmaple:
-``libmaple.h``
-==============
+``<libmaple/libmaple.h>``
+=========================
Base include file for libmaple.
diff --git a/source/libmaple/api/libmaple_types.rst b/source/libmaple/api/libmaple_types.rst
index 7fed5dc..5ca446e 100644
--- a/source/libmaple/api/libmaple_types.rst
+++ b/source/libmaple/api/libmaple_types.rst
@@ -1,12 +1,15 @@
.. highlight:: c
.. _libmaple-libmaple_types:
-``libmaple_types.h``
-====================
+``<libmaple/libmaple_types.h>``
+===============================
Defines the base types and type-related macros used throughout the
rest of libmaple.
+.. contents:: Contents
+ :local:
+
Integral Types
--------------
@@ -22,22 +25,61 @@ Integral Types
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
- This is a macro for ``volatile`` which is used to denote 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
+ 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:: __attr_flash
+.. c:macro:: __weak
- This is a macro for a GCC ``__attribute__`` which (when using the
- linker scripts provided with libmaple) will cause the variable
- being marked to be stored in Flash, rather than SRAM. The
- variable's value may be read like that of any other variable, but
- it may not be written.
+ Macro for ``__attribute__((weak))``.
-Other typedefs
---------------
+.. 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/source/libmaple/api/nvic.rst b/source/libmaple/api/nvic.rst
index b22c94b..505e36e 100644
--- a/source/libmaple/api/nvic.rst
+++ b/source/libmaple/api/nvic.rst
@@ -1,25 +1,44 @@
.. highlight:: c
.. _libmaple-nvic:
-``nvic.h``
-==========
+``<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:
-Types
------
-
-.. doxygenstruct:: nvic_reg_map
-.. doxygenenum:: nvic_irq_num
-
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
---------
@@ -33,10 +52,14 @@ Functions
.. doxygenfunction:: nvic_irq_disable_all
.. doxygenfunction:: nvic_sys_reset
-Register Map Base Pointers
---------------------------
+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
------------------------
diff --git a/source/libmaple/api/rcc-reg-bits.txt b/source/libmaple/api/rcc-reg-bits.txt
new file mode 100644
index 0000000..6b1133d
--- /dev/null
+++ b/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/source/libmaple/api/rcc.rst b/source/libmaple/api/rcc.rst
index 4b96c00..ce58ec8 100644
--- a/source/libmaple/api/rcc.rst
+++ b/source/libmaple/api/rcc.rst
@@ -1,377 +1,360 @@
.. highlight:: c
.. _libmaple-rcc:
-``rcc.h``
-=========
+``<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
-Types
------
+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>`.
-.. doxygenstruct:: rcc_reg_map
.. doxygenenum:: rcc_sysclk_src
-.. doxygenenum:: rcc_pllsrc
-.. doxygenenum:: rcc_pll_multiplier
-.. doxygenenum:: rcc_clk_id
-.. doxygenenum:: rcc_clk_domain
-.. doxygenenum:: rcc_prescaler
-.. doxygenenum:: rcc_adc_divider
-.. doxygenenum:: rcc_apb1_divider
-.. doxygenenum:: rcc_apb2_divider
-.. doxygenenum:: rcc_ahb_divider
-Devices
--------
+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
-None.
+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
---------
-.. doxygenfunction:: rcc_clk_init
+.. _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
-Register Map Base Pointers
---------------------------
+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
------------------------
-Clock control register
-~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: RCC_CR_PLLRDY_BIT
-.. doxygendefine:: RCC_CR_PLLON_BIT
-.. doxygendefine:: RCC_CR_CSSON_BIT
-.. doxygendefine:: RCC_CR_HSEBYP_BIT
-.. doxygendefine:: RCC_CR_HSERDY_BIT
-.. doxygendefine:: RCC_CR_HSEON_BIT
-.. doxygendefine:: RCC_CR_HSIRDY_BIT
-.. doxygendefine:: RCC_CR_HSION_BIT
-
-.. doxygendefine:: RCC_CR_PLLRDY
-.. doxygendefine:: RCC_CR_PLLON
-.. doxygendefine:: RCC_CR_CSSON
-.. doxygendefine:: RCC_CR_HSEBYP
-.. doxygendefine:: RCC_CR_HSERDY
-.. doxygendefine:: RCC_CR_HSEON
-.. doxygendefine:: RCC_CR_HSICAL
-.. doxygendefine:: RCC_CR_HSITRIM
-.. doxygendefine:: RCC_CR_HSIRDY
-.. doxygendefine:: RCC_CR_HSION
-
-Clock configuration register
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: RCC_CFGR_USBPRE_BIT
-.. doxygendefine:: RCC_CFGR_PLLXTPRE_BIT
-.. doxygendefine:: RCC_CFGR_PLLSRC_BIT
-
-.. doxygendefine:: RCC_CFGR_MCO
-.. doxygendefine:: RCC_CFGR_USBPRE
-.. doxygendefine:: RCC_CFGR_PLLMUL
-.. doxygendefine:: RCC_CFGR_PLLXTPRE
-.. doxygendefine:: RCC_CFGR_PLLSRC
-.. doxygendefine:: RCC_CFGR_ADCPRE
-.. doxygendefine:: RCC_CFGR_PPRE2
-.. doxygendefine:: RCC_CFGR_PPRE1
-.. doxygendefine:: RCC_CFGR_HPRE
-.. doxygendefine:: RCC_CFGR_SWS
-.. doxygendefine:: RCC_CFGR_SWS_PLL
-.. doxygendefine:: RCC_CFGR_SWS_HSE
-.. doxygendefine:: RCC_CFGR_SW
-.. doxygendefine:: RCC_CFGR_SW_PLL
-.. doxygendefine:: RCC_CFGR_SW_HSE
-
-Clock interrupt register
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: RCC_CIR_CSSC_BIT
-.. doxygendefine:: RCC_CIR_PLLRDYC_BIT
-.. doxygendefine:: RCC_CIR_HSERDYC_BIT
-.. doxygendefine:: RCC_CIR_HSIRDYC_BIT
-.. doxygendefine:: RCC_CIR_LSERDYC_BIT
-.. doxygendefine:: RCC_CIR_LSIRDYC_BIT
-.. doxygendefine:: RCC_CIR_PLLRDYIE_BIT
-.. doxygendefine:: RCC_CIR_HSERDYIE_BIT
-.. doxygendefine:: RCC_CIR_HSIRDYIE_BIT
-.. doxygendefine:: RCC_CIR_LSERDYIE_BIT
-.. doxygendefine:: RCC_CIR_LSIRDYIE_BIT
-.. doxygendefine:: RCC_CIR_CSSF_BIT
-.. doxygendefine:: RCC_CIR_PLLRDYF_BIT
-.. doxygendefine:: RCC_CIR_HSERDYF_BIT
-.. doxygendefine:: RCC_CIR_HSIRDYF_BIT
-.. doxygendefine:: RCC_CIR_LSERDYF_BIT
-.. doxygendefine:: RCC_CIR_LSIRDYF_BIT
-
-.. doxygendefine:: RCC_CIR_CSSC
-.. doxygendefine:: RCC_CIR_PLLRDYC
-.. doxygendefine:: RCC_CIR_HSERDYC
-.. doxygendefine:: RCC_CIR_HSIRDYC
-.. doxygendefine:: RCC_CIR_LSERDYC
-.. doxygendefine:: RCC_CIR_LSIRDYC
-.. doxygendefine:: RCC_CIR_PLLRDYIE
-.. doxygendefine:: RCC_CIR_HSERDYIE
-.. doxygendefine:: RCC_CIR_HSIRDYIE
-.. doxygendefine:: RCC_CIR_LSERDYIE
-.. doxygendefine:: RCC_CIR_LSIRDYIE
-.. doxygendefine:: RCC_CIR_CSSF
-.. doxygendefine:: RCC_CIR_PLLRDYF
-.. doxygendefine:: RCC_CIR_HSERDYF
-.. doxygendefine:: RCC_CIR_HSIRDYF
-.. doxygendefine:: RCC_CIR_LSERDYF
-.. doxygendefine:: RCC_CIR_LSIRDYF
-
-APB2 peripheral reset register
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: RCC_APB2RSTR_TIM11RST_BIT
-.. doxygendefine:: RCC_APB2RSTR_TIM10RST_BIT
-.. doxygendefine:: RCC_APB2RSTR_TIM9RST_BIT
-.. doxygendefine:: RCC_APB2RSTR_ADC3RST_BIT
-.. doxygendefine:: RCC_APB2RSTR_USART1RST_BIT
-.. doxygendefine:: RCC_APB2RSTR_TIM8RST_BIT
-.. doxygendefine:: RCC_APB2RSTR_SPI1RST_BIT
-.. doxygendefine:: RCC_APB2RSTR_TIM1RST_BIT
-.. doxygendefine:: RCC_APB2RSTR_ADC2RST_BIT
-.. doxygendefine:: RCC_APB2RSTR_ADC1RST_BIT
-.. doxygendefine:: RCC_APB2RSTR_IOPGRST_BIT
-.. doxygendefine:: RCC_APB2RSTR_IOPFRST_BIT
-.. doxygendefine:: RCC_APB2RSTR_IOPERST_BIT
-.. doxygendefine:: RCC_APB2RSTR_IOPDRST_BIT
-.. doxygendefine:: RCC_APB2RSTR_IOPCRST_BIT
-.. doxygendefine:: RCC_APB2RSTR_IOPBRST_BIT
-.. doxygendefine:: RCC_APB2RSTR_IOPARST_BIT
-.. doxygendefine:: RCC_APB2RSTR_AFIORST_BIT
-
-.. doxygendefine:: RCC_APB2RSTR_TIM11RST
-.. doxygendefine:: RCC_APB2RSTR_TIM10RST
-.. doxygendefine:: RCC_APB2RSTR_TIM9RST
-.. doxygendefine:: RCC_APB2RSTR_ADC3RST
-.. doxygendefine:: RCC_APB2RSTR_USART1RST
-.. doxygendefine:: RCC_APB2RSTR_TIM8RST
-.. doxygendefine:: RCC_APB2RSTR_SPI1RST
-.. doxygendefine:: RCC_APB2RSTR_TIM1RST
-.. doxygendefine:: RCC_APB2RSTR_ADC2RST
-.. doxygendefine:: RCC_APB2RSTR_ADC1RST
-.. doxygendefine:: RCC_APB2RSTR_IOPGRST
-.. doxygendefine:: RCC_APB2RSTR_IOPFRST
-.. doxygendefine:: RCC_APB2RSTR_IOPERST
-.. doxygendefine:: RCC_APB2RSTR_IOPDRST
-.. doxygendefine:: RCC_APB2RSTR_IOPCRST
-.. doxygendefine:: RCC_APB2RSTR_IOPBRST
-.. doxygendefine:: RCC_APB2RSTR_IOPARST
-.. doxygendefine:: RCC_APB2RSTR_AFIORST
-
-APB1 peripheral reset register
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: RCC_APB1RSTR_DACRST_BIT
-.. doxygendefine:: RCC_APB1RSTR_PWRRST_BIT
-.. doxygendefine:: RCC_APB1RSTR_BKPRST_BIT
-.. doxygendefine:: RCC_APB1RSTR_CANRST_BIT
-.. doxygendefine:: RCC_APB1RSTR_USBRST_BIT
-.. doxygendefine:: RCC_APB1RSTR_I2C2RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_I2C1RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_UART5RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_UART4RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_USART3RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_USART2RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_SPI3RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_SPI2RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_WWDRST_BIT
-.. doxygendefine:: RCC_APB1RSTR_TIM14RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_TIM13RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_TIM12RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_TIM7RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_TIM6RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_TIM5RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_TIM4RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_TIM3RST_BIT
-.. doxygendefine:: RCC_APB1RSTR_TIM2RST_BIT
-
-.. doxygendefine:: RCC_APB1RSTR_DACRST
-.. doxygendefine:: RCC_APB1RSTR_PWRRST
-.. doxygendefine:: RCC_APB1RSTR_BKPRST
-.. doxygendefine:: RCC_APB1RSTR_CANRST
-.. doxygendefine:: RCC_APB1RSTR_USBRST
-.. doxygendefine:: RCC_APB1RSTR_I2C2RST
-.. doxygendefine:: RCC_APB1RSTR_I2C1RST
-.. doxygendefine:: RCC_APB1RSTR_UART5RST
-.. doxygendefine:: RCC_APB1RSTR_UART4RST
-.. doxygendefine:: RCC_APB1RSTR_USART3RST
-.. doxygendefine:: RCC_APB1RSTR_USART2RST
-.. doxygendefine:: RCC_APB1RSTR_SPI3RST
-.. doxygendefine:: RCC_APB1RSTR_SPI2RST
-.. doxygendefine:: RCC_APB1RSTR_WWDRST
-.. doxygendefine:: RCC_APB1RSTR_TIM14RST
-.. doxygendefine:: RCC_APB1RSTR_TIM13RST
-.. doxygendefine:: RCC_APB1RSTR_TIM12RST
-.. doxygendefine:: RCC_APB1RSTR_TIM7RST
-.. doxygendefine:: RCC_APB1RSTR_TIM6RST
-.. doxygendefine:: RCC_APB1RSTR_TIM5RST
-.. doxygendefine:: RCC_APB1RSTR_TIM4RST
-.. doxygendefine:: RCC_APB1RSTR_TIM3RST
-.. doxygendefine:: RCC_APB1RSTR_TIM2RST
-
-AHB peripheral clock enable register
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: RCC_AHBENR_SDIOEN_BIT
-.. doxygendefine:: RCC_AHBENR_FSMCEN_BIT
-.. doxygendefine:: RCC_AHBENR_CRCEN_BIT
-.. doxygendefine:: RCC_AHBENR_FLITFEN_BIT
-.. doxygendefine:: RCC_AHBENR_SRAMEN_BIT
-.. doxygendefine:: RCC_AHBENR_DMA2EN_BIT
-.. doxygendefine:: RCC_AHBENR_DMA1EN_BIT
-
-.. doxygendefine:: RCC_AHBENR_SDIOEN
-.. doxygendefine:: RCC_AHBENR_FSMCEN
-.. doxygendefine:: RCC_AHBENR_CRCEN
-.. doxygendefine:: RCC_AHBENR_FLITFEN
-.. doxygendefine:: RCC_AHBENR_SRAMEN
-.. doxygendefine:: RCC_AHBENR_DMA2EN
-.. doxygendefine:: RCC_AHBENR_DMA1EN
-
-APB2 peripheral clock enable register
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+These are given as source code. Available register bit definitions
+vary by target.
-.. doxygendefine:: RCC_APB2ENR_TIM11EN_BIT
-.. doxygendefine:: RCC_APB2ENR_TIM10EN_BIT
-.. doxygendefine:: RCC_APB2ENR_TIM9EN_BIT
-.. doxygendefine:: RCC_APB2ENR_ADC3EN_BIT
-.. doxygendefine:: RCC_APB2ENR_USART1EN_BIT
-.. doxygendefine:: RCC_APB2ENR_TIM8EN_BIT
-.. doxygendefine:: RCC_APB2ENR_SPI1EN_BIT
-.. doxygendefine:: RCC_APB2ENR_TIM1EN_BIT
-.. doxygendefine:: RCC_APB2ENR_ADC2EN_BIT
-.. doxygendefine:: RCC_APB2ENR_ADC1EN_BIT
-.. doxygendefine:: RCC_APB2ENR_IOPGEN_BIT
-.. doxygendefine:: RCC_APB2ENR_IOPFEN_BIT
-.. doxygendefine:: RCC_APB2ENR_IOPEEN_BIT
-.. doxygendefine:: RCC_APB2ENR_IOPDEN_BIT
-.. doxygendefine:: RCC_APB2ENR_IOPCEN_BIT
-.. doxygendefine:: RCC_APB2ENR_IOPBEN_BIT
-.. doxygendefine:: RCC_APB2ENR_IOPAEN_BIT
-.. doxygendefine:: RCC_APB2ENR_AFIOEN_BIT
-
-.. doxygendefine:: RCC_APB2ENR_TIM11EN
-.. doxygendefine:: RCC_APB2ENR_TIM10EN
-.. doxygendefine:: RCC_APB2ENR_TIM9EN
-.. doxygendefine:: RCC_APB2ENR_ADC3EN
-.. doxygendefine:: RCC_APB2ENR_USART1EN
-.. doxygendefine:: RCC_APB2ENR_TIM8EN
-.. doxygendefine:: RCC_APB2ENR_SPI1EN
-.. doxygendefine:: RCC_APB2ENR_TIM1EN
-.. doxygendefine:: RCC_APB2ENR_ADC2EN
-.. doxygendefine:: RCC_APB2ENR_ADC1EN
-.. doxygendefine:: RCC_APB2ENR_IOPGEN
-.. doxygendefine:: RCC_APB2ENR_IOPFEN
-.. doxygendefine:: RCC_APB2ENR_IOPEEN
-.. doxygendefine:: RCC_APB2ENR_IOPDEN
-.. doxygendefine:: RCC_APB2ENR_IOPCEN
-.. doxygendefine:: RCC_APB2ENR_IOPBEN
-.. doxygendefine:: RCC_APB2ENR_IOPAEN
-.. doxygendefine:: RCC_APB2ENR_AFIOEN
-
-APB1 peripheral clock enable register
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. We need this include to avoid crashing Emacs's ReST parser. Yuck.
+
+.. include:: rcc-reg-bits.txt
+
+Deprecated Functionality
+------------------------
-.. doxygendefine:: RCC_APB1ENR_DACEN_BIT
-.. doxygendefine:: RCC_APB1ENR_PWREN_BIT
-.. doxygendefine:: RCC_APB1ENR_BKPEN_BIT
-.. doxygendefine:: RCC_APB1ENR_CANEN_BIT
-.. doxygendefine:: RCC_APB1ENR_USBEN_BIT
-.. doxygendefine:: RCC_APB1ENR_I2C2EN_BIT
-.. doxygendefine:: RCC_APB1ENR_I2C1EN_BIT
-.. doxygendefine:: RCC_APB1ENR_UART5EN_BIT
-.. doxygendefine:: RCC_APB1ENR_UART4EN_BIT
-.. doxygendefine:: RCC_APB1ENR_USART3EN_BIT
-.. doxygendefine:: RCC_APB1ENR_USART2EN_BIT
-.. doxygendefine:: RCC_APB1ENR_SPI3EN_BIT
-.. doxygendefine:: RCC_APB1ENR_SPI2EN_BIT
-.. doxygendefine:: RCC_APB1ENR_WWDEN_BIT
-.. doxygendefine:: RCC_APB1ENR_TIM14EN_BIT
-.. doxygendefine:: RCC_APB1ENR_TIM13EN_BIT
-.. doxygendefine:: RCC_APB1ENR_TIM12EN_BIT
-.. doxygendefine:: RCC_APB1ENR_TIM7EN_BIT
-.. doxygendefine:: RCC_APB1ENR_TIM6EN_BIT
-.. doxygendefine:: RCC_APB1ENR_TIM5EN_BIT
-.. doxygendefine:: RCC_APB1ENR_TIM4EN_BIT
-.. doxygendefine:: RCC_APB1ENR_TIM3EN_BIT
-.. doxygendefine:: RCC_APB1ENR_TIM2EN_BIT
-
-.. doxygendefine:: RCC_APB1ENR_DACEN
-.. doxygendefine:: RCC_APB1ENR_PWREN
-.. doxygendefine:: RCC_APB1ENR_BKPEN
-.. doxygendefine:: RCC_APB1ENR_CANEN
-.. doxygendefine:: RCC_APB1ENR_USBEN
-.. doxygendefine:: RCC_APB1ENR_I2C2EN
-.. doxygendefine:: RCC_APB1ENR_I2C1EN
-.. doxygendefine:: RCC_APB1ENR_UART5EN
-.. doxygendefine:: RCC_APB1ENR_UART4EN
-.. doxygendefine:: RCC_APB1ENR_USART3EN
-.. doxygendefine:: RCC_APB1ENR_USART2EN
-.. doxygendefine:: RCC_APB1ENR_SPI3EN
-.. doxygendefine:: RCC_APB1ENR_SPI2EN
-.. doxygendefine:: RCC_APB1ENR_WWDEN
-.. doxygendefine:: RCC_APB1ENR_TIM14EN
-.. doxygendefine:: RCC_APB1ENR_TIM13EN
-.. doxygendefine:: RCC_APB1ENR_TIM12EN
-.. doxygendefine:: RCC_APB1ENR_TIM7EN
-.. doxygendefine:: RCC_APB1ENR_TIM6EN
-.. doxygendefine:: RCC_APB1ENR_TIM5EN
-.. doxygendefine:: RCC_APB1ENR_TIM4EN
-.. doxygendefine:: RCC_APB1ENR_TIM3EN
-.. doxygendefine:: RCC_APB1ENR_TIM2EN
-
-Backup domain control register
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: RCC_BDCR_BDRST_BIT
-.. doxygendefine:: RCC_BDCR_RTCEN_BIT
-.. doxygendefine:: RCC_BDCR_LSEBYP_BIT
-.. doxygendefine:: RCC_BDCR_LSERDY_BIT
-.. doxygendefine:: RCC_BDCR_LSEON_BIT
-
-.. doxygendefine:: RCC_BDCR_BDRST
-.. doxygendefine:: RCC_BDCR_RTCEN
-.. doxygendefine:: RCC_BDCR_RTCSEL
-.. doxygendefine:: RCC_BDCR_RTCSEL_NONE
-.. doxygendefine:: RCC_BDCR_RTCSEL_LSE
-.. doxygendefine:: RCC_BDCR_RTCSEL_HSE
-.. doxygendefine:: RCC_BDCR_LSEBYP
-.. doxygendefine:: RCC_BDCR_LSERDY
-.. doxygendefine:: RCC_BDCR_LSEON
-
-Control/status register
-~~~~~~~~~~~~~~~~~~~~~~~
-
-.. doxygendefine:: RCC_CSR_LPWRRSTF_BIT
-.. doxygendefine:: RCC_CSR_WWDGRSTF_BIT
-.. doxygendefine:: RCC_CSR_IWDGRSTF_BIT
-.. doxygendefine:: RCC_CSR_SFTRSTF_BIT
-.. doxygendefine:: RCC_CSR_PORRSTF_BIT
-.. doxygendefine:: RCC_CSR_PINRSTF_BIT
-.. doxygendefine:: RCC_CSR_RMVF_BIT
-.. doxygendefine:: RCC_CSR_LSIRDY_BIT
-.. doxygendefine:: RCC_CSR_LSION_BIT
-
-.. doxygendefine:: RCC_CSR_LPWRRSTF
-.. doxygendefine:: RCC_CSR_WWDGRSTF
-.. doxygendefine:: RCC_CSR_IWDGRSTF
-.. doxygendefine:: RCC_CSR_SFTRSTF
-.. doxygendefine:: RCC_CSR_PORRSTF
-.. doxygendefine:: RCC_CSR_PINRSTF
-.. doxygendefine:: RCC_CSR_RMVF
-.. doxygendefine:: RCC_CSR_LSIRDY
-.. doxygendefine:: RCC_CSR_LSION
+.. _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/source/libmaple/api/ring_buffer.rst b/source/libmaple/api/ring_buffer.rst
index e9b6637..ef082dd 100644
--- a/source/libmaple/api/ring_buffer.rst
+++ b/source/libmaple/api/ring_buffer.rst
@@ -1,8 +1,8 @@
.. highlight:: c
.. _libmaple-ring_buffer:
-``ring_buffer.h``
-=================
+``<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.
diff --git a/source/libmaple/api/stm32.rst b/source/libmaple/api/stm32.rst
index 6e631b0..335bda4 100644
--- a/source/libmaple/api/stm32.rst
+++ b/source/libmaple/api/stm32.rst
@@ -1,26 +1,118 @@
.. highlight:: c
.. _libmaple-stm32:
-``stm32.h``
-===========
+``<libmaple/stm32.h>``
+======================
-General STM32-specific definitions. This file is currently somewhat
-incomplete, but it will form the future basis for MCU-specific (rather
-than board-specific, which belongs in :ref:`Wirish
-<libmaple-vs-wirish>`) configuration.
+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>`).
-Defines
--------
+.. 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
-.. doxygendefine:: STM32_NR_INTERRUPTS
-.. doxygendefine:: STM32_NR_GPIO_PORTS
+
+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
-.. doxygendefine:: STM32_SRAM_END
-Deprecated Defines
-------------------
+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
diff --git a/source/libmaple/api/usart.rst b/source/libmaple/api/usart.rst
index 1575a8f..68f2c37 100644
--- a/source/libmaple/api/usart.rst
+++ b/source/libmaple/api/usart.rst
@@ -34,6 +34,7 @@ Functions
.. doxygenfunction:: usart_disable
.. doxygenfunction:: usart_disable_all
.. doxygenfunction:: usart_foreach
+.. doxygenfunction:: usart_rx
.. doxygenfunction:: usart_tx
.. doxygenfunction:: usart_putudec
.. doxygenfunction:: usart_putc
diff --git a/source/libmaple/api/util.rst b/source/libmaple/api/util.rst
index 06c9246..54377c0 100644
--- a/source/libmaple/api/util.rst
+++ b/source/libmaple/api/util.rst
@@ -1,8 +1,8 @@
.. highlight:: c
.. _libmaple-util:
-``util.h``
-==========
+``<libmaple/util.h>``
+=====================
.. TODO [0.2.0?] clean this up.
@@ -14,17 +14,20 @@ Miscellaneous utility macros and procedures.
Bit Manipulation
----------------
-::
+The following macros are useful for bit manipulation.
- #define BIT(shift) (1UL << (shift))
- #define BIT_MASK_SHIFT(mask, shift) ((mask) << (shift))
- /** Gets bits m to n of x */
- #define GET_BITS(x, m, n) ((((uint32)x) << (31 - (n))) >> ((31 - (n)) + (m)))
- #define IS_POWER_OF_TWO(v) (v && !(v & (v - 1)))
+.. 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
diff --git a/source/libmaple/apis.rst b/source/libmaple/apis.rst
index f493406..31f4902 100644
--- a/source/libmaple/apis.rst
+++ b/source/libmaple/apis.rst
@@ -1,7 +1,7 @@
.. _libmaple-apis:
-APIs
-====
+``libmaple`` API Index
+======================
This is the master index for libmaple proper's APIs.
diff --git a/source/libmaple/overview.rst b/source/libmaple/overview.rst
index 21d1a72..006f1d8 100644
--- a/source/libmaple/overview.rst
+++ b/source/libmaple/overview.rst
@@ -5,9 +5,12 @@
Overview
========
-This page is a general overview of libmaple proper. It provides a
-general perspective of the library's goals and design. Examples are
-given from libmaple's sources.
+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:
@@ -15,170 +18,321 @@ given from libmaple's sources.
Design Goals
------------
-The central goal of the libmaple project is to provide a pleasant,
-consistent set of interfaces for dealing with the various peripherals
-on the STM32 line.
-
-Let's start with the basics. If you're interested in low-level details
-on the STM32, then you're going to spend a lot of quality time wading
-through `ST RM0008
-<http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/CD00171190.pdf>`_.
-That document is the single most important tool in your toolbox. It
-is the authoritative documentation for the capabilities and register
-interfaces of the STM32 line.
-
-Perhaps you haven't read it in detail, but maybe you've at least
-thumbed through a few of the sections, trying to gain some
-understanding of what's going on. If you've done that (and if you
-haven't, just take our word for it), then you know that underneath the
-covers, *everything* is controlled by messing with bits in the
-seemingly endless collections of registers specific to every
-peripheral. The :ref:`USARTs <usart>` have data registers; (some of
-the) the :ref:`timers <timers>` have capture/compare registers, the
-:ref:`GPIOs <gpio>` have output data registers, etc.
-
-For the most part, Wirish does everything it can to hide this truth
-from you. That's because when you really just want to get your robot
-to fly, your LEDs to blink, 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 messing with registers.
-
-That's fine! In fact, it's our explicit goal for Wirish to be good
-enough that most people never need to know libmaple proper even
-exists. We want to make programming our boards as easy as possible,
-after all. But the day may come when you want to add a library for an
-as-yet unsupported peripheral, or you want to do something we didn't
-anticipate, or you'd like to squeeze a little more speed out of a
-critical section in your program. Or maybe you're just curious!
-
-If anything in the above paragraph describes you, then you'll find
-that you need a way to translate your knowledge of RM0008 into
-software. We imagine (if you're anything like us) you want to spend
-the least amount of time you possibly can doing that
-translation. Ideally, once you've finished your design, you want some
-way to start reading and writing code right away, without having to
-bushwhack your way through a thicket of clunky APIs.
-
-The central abstractions we've chosen to accomplish the above goals
-are *register maps* and *devices*. Register maps are just structs
-which encapsulate the layout of the IO-mapped memory regions
-corresponding to a peripheral's registers. Devices encapsulate a
-peripheral's register map as well as any other necessary information
-needed to operate on it. Peripheral support routines generally
-operate on devices rather than register maps.
-
-Devices
--------
-
-At the highest level, you'll be dealing with *devices*, where a
-"device" is a general term for any particular piece of hardware you
-might encounter. So, for example, an analog to digital converter is a
-device. So is a USART. So is a GPIO port. In this section, we'll
-consider some hypothetical "xxx" device.
-
-The first thing you need to know is that the header file for dealing
-with xxx devices is, naturally enough, called ``xxx.h``. So if you
-want to interface with the :ref:`ADCs <adc>`, just ``#include
-"adc.h"``.
-
-Inside of ``xxx.h``, there will be a declaration for a ``struct
-xxx_dev`` type. This type encapsulates all of the information we keep
-track of for that xxx. So, for example, in ``adc.h``, there's a
-``struct adc_dev``::
-
- /** ADC device type. */
+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; /**< Register map */
- rcc_clk_id clk_id; /**< RCC clock information */
+ adc_reg_map *regs;
+ rcc_clk_id clk_id;
} adc_dev;
-The ADCs aren't particularly complicated. All we keep track of for an
-ADC device is a pointer to its register map (which keeps track of all
-of its registers' bits; see :ref:`below <libmaple-overview-regmaps>`
-for more details), and an identifying piece of information which tells
-the RCC (reset and clock control) interface how to turn the ADC on and
-reset its registers to their default values.
-
-The timers on the STM32 line are more involved than the ADCs, so a
-``timer_dev`` has to keep track of a bit more information::
-
- /** Timer device type */
- typedef struct timer_dev {
- timer_reg_map regs; /**< Register map */
- rcc_clk_id clk_id; /**< RCC clock information */
- timer_type type; /**< Timer's type */
- voidFuncPtr handlers[]; /**< User IRQ handlers */
- } timer_dev;
-
-However, as you can see, both ADC and timer devices are named
-according to a single scheme, and store similar information.
-
-``xxx.h`` will also declare pointers to the actual devices you need to
-deal with, called ``XXX1``, ``XXX2``, etc. (or just ``XXX``, if
-there's only one) [#fgpio]_. For instance, on the Maple's
-microcontroller (the STM32F103RBT6), there are two ADCs.
-Consequently, in ``adc.h``, there are declarations for dealing with
-ADC devices one and two::
-
- extern const adc_dev *ADC1;
- extern const adc_dev *ADC2;
-
-In general, each device needs to be initialized before it can be used.
-libmaple provides this initialization routine for each peripheral
-``xxx``; its name is ``xxx_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 dma.h */
- void dma_init(dma_dev *dev);
-
- /* From 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
-``xxx_enable()``, and often take additional arguments which specify a
-particular configuration for the peripheral. Some examples::
+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::
- /* From usart.h */
- void usart_enable(usart_dev *dev);
-
- /* From i2c.h */
- void i2c_master_enable(i2c_dev *dev, uint32 flags);
+ void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate);
-After you've initialized, and potentially enabled, your peripheral, it
-is now time to begin using it. The file ``xxx.h`` contains other
-convenience functions for dealing with xxx devices. For instance,
-here are a few from ``adc.h``::
+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);
+ }
- void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate);
- uint32 adc_read(const adc_dev *dev, uint8 channel);
+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.
-We aim to enable libmaple's users to interact with peripherals through
-devices as much as possible, rather than having to break the
-abstraction and consider individual registers. However, there will
-always be a need for low-level access. To allow for that, libmaple
-provides *register maps* as a consistent set of names and abstractions
-for dealing with registers and their bits.
+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
-------------
-A *register map* is just a C struct which names and provides access to
-a peripheral's registers. These registers are usually mapped to
-contiguous regions of memory (though at times unusable or reserved
-regions exist between a peripheral's registers). Here's an example
-register map, from ``dac.h`` (``__io`` is just libmaple's way of
-saying ``volatile`` when referring to register values)::
+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)::
- /** DAC register map. */
typedef struct dac_reg_map {
__io uint32 CR; /**< Control register */
__io uint32 SWTRIGR; /**< Software trigger register */
@@ -204,89 +358,87 @@ saying ``volatile`` when referring to register values)::
__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.
-There are two things to notice here. First, if 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 (RM0008:
-DAC_DHR12R1) is the ``DHR12R1`` field in a ``dac_reg_map``. Second,
-if RM0008 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 ``xxx.h``, and you want to mess with some
-particular register. What's the name of the ``xxx_reg_map`` variable
-you want? That depends on if there's more than one xxx or not. If
-there's only one xxx, then libmaple guarantees there will be a
-``#define`` that looks like like this::
+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 XXX_BASE ((struct xxx_reg_map*)0xDEADBEEF)
+ #define FOO_BASE ((struct foo_reg_map*)0xDEADBEEF)
That is, you're guaranteed there will be a pointer to the (only)
-``xxx_reg_map`` you want, and it will be called
-``XXX_BASE``. (``0xDEADBEEF`` is the register map's *base address*, or
-the fixed location in memory where the register map begins). Here's a
-concrete example from ``dac.h``::
+``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)
+ #define DAC_BASE ((struct dac_reg_map*)0x40007400)
-How can you use these? This is perhaps best explained by example.
+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 (RM0008: DAC_DHR12L1), you could write::
+ holding register (DAC_DHR12L1), you would write::
DAC_BASE->DHR12L1 = 2048;
-* In order to read the DAC control register, you could write::
+* In order to read the DAC control register, you would write::
uint32 cr = DAC_BASE->CR;
-The microcontroller takes care of converting reads and writes from a
-register's IO-mapped memory regions into reads and writes to the
-corresponding hardware registers.
-
-That covers the case where there's a single xxx peripheral. If
-there's more than one (say, if there are *n*), then ``xxx.h`` provides
-the following::
+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 XXX1_BASE ((struct xxx_reg_map*)0xDEADBEEF)
- #define XXX2_BASE ((struct xxx_reg_map*)0xF00DF00D)
+ #define FOO1_BASE ((struct foo_reg_map*)0xDEADBEEF)
+ #define FOO2_BASE ((struct foo_reg_map*)0xF00DF00D)
...
- #define XXXn_BASE ((struct xxx_reg_map*)0x13AF1AB5)
+ #define FOOn_BASE ((struct foo_reg_map*)0x1EAF1AB5)
-Here are some examples from ``adc.h``::
+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)
+ #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 might write::
+results of ADC conversion are stored), you would write::
uint32 converted_result = ADC1_BASE->DR;
Register Bit Definitions
------------------------
-In ``xxx.h``, there will also be a variety of #defines for dealing
-with interesting bits in the xxx registers, called *register bit
-definitions*. These are named according to the scheme
-``XXX_REG_FIELD``, where "``REG``" refers to the register, and
-"``FIELD``" refers to the bit or bits in ``REG`` that are special.
-
-.. TODO image of the bit layout of a DMA_CCR register
-
-Again, this is probably best explained by example. Each Direct Memory
-Access (DMA) controller's register map has a certain number of channel
-configuration registers (RM0008: 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::
-
- /* From dma.h */
+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 BIT(DMA_CCR_MEM2MEM_BIT)
+ #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)
@@ -294,7 +446,7 @@ register bit definitions for those fields::
#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 (RM0008: DMA_CCR2), you can write::
+channel configuration register 2 (DMA_CCR2), you can write::
if (DMA1_BASE->CCR2 & DMA_CCR_MEM2MEM) {
/* MEM2MEM is set */
@@ -304,33 +456,61 @@ 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
-check the priority level of a DMA transfer, you can write::
-
- switch (DMA1_BASE->CCR2 & DMA_CCR_PL) {
- case DMA_CCR_PL_LOW:
- /* handle low priority case */
- case DMA_CCR_PL_MEDIUM:
- /* handle medium priority case */
- case DMA_CCR_PL_HIGH:
- /* handle high priority case */
- case DMA_CCR_PL_VERY_HIGH:
- /* handle very high priority case */
- }
+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!
+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::
-What Next?
-----------
+ /* From <libmaple/dma.h> */
+ void dma_init(dma_dev *dev);
-After you've read this page, you can proceed to the :ref:`libmaple API
-listing <libmaple-apis>`. From there, you can read documentation and
-follow links to the current source code for those files on `libmaple's
-GitHub page <https://github.com/leaflabs/libmaple>`_.
+ /* 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] For consistency with RM0008, GPIO ports are given letters
- instead of numbers (``GPIOA`` and ``GPIOB`` instead of
- ``GPIO1`` and ``GPIO2``, etc.).
+.. [#fgpio] As an exception, GPIO ports are given letters instead of
+ numbers (``GPIOA`` and ``GPIOB`` instead of ``GPIO1`` and
+ ``GPIO2``, etc.).