aboutsummaryrefslogtreecommitdiff
path: root/lib/stm32/common
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stm32/common')
-rw-r--r--lib/stm32/common/crc_common_all.c82
-rw-r--r--lib/stm32/common/dac_common_all.c516
-rw-r--r--lib/stm32/common/i2c_common_all.c411
-rw-r--r--lib/stm32/common/iwdg_common_all.c140
-rw-r--r--lib/stm32/common/spi_common_all.c727
-rw-r--r--lib/stm32/common/usart_common_all.c452
6 files changed, 2328 insertions, 0 deletions
diff --git a/lib/stm32/common/crc_common_all.c b/lib/stm32/common/crc_common_all.c
new file mode 100644
index 0000000..d65d1b7
--- /dev/null
+++ b/lib/stm32/common/crc_common_all.c
@@ -0,0 +1,82 @@
+/** @addtogroup crc_file
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2012 Karl Palsson <karlp@remake.is>
+
+@date 15 October 2012
+
+LGPL License Terms @ref lgpl_license
+ */
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 Karl Palsson <karlp@remake.is>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/crc.h>
+
+/**@{*/
+
+/*-----------------------------------------------------------------------------*/
+/** @brief CRC Reset.
+
+Reset the CRC unit and forces the data register to all 1s.
+
+*/
+
+void crc_reset(void)
+{
+ CRC_CR |= CRC_CR_RESET;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief CRC Calculate.
+
+Writes a data word to the register, the write operation stalling until the
+computation is complete.
+
+@param[in] data Unsigned int32.
+@returns int32 Computed CRC result
+*/
+
+u32 crc_calculate(u32 data)
+{
+ CRC_DR = data;
+ // Data sheet says this blocks until it's ready....
+ return CRC_DR;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief CRC Calculate of a Block of Data.
+
+Writes data words consecutively to the register, the write operation stalling
+until the computation of each word is complete.
+
+@param[in] datap Unsigned int32. pointer to an array of 32 bit data words.
+@returns int32 Final computed CRC result
+*/
+
+u32 crc_calculate_block(u32 *datap, int size)
+{
+ int i;
+ for (i = 0; i < size; i++) {
+ CRC_DR = datap[i];
+ }
+ return CRC_DR;
+}
+/**@}*/
+
diff --git a/lib/stm32/common/dac_common_all.c b/lib/stm32/common/dac_common_all.c
new file mode 100644
index 0000000..a6be233
--- /dev/null
+++ b/lib/stm32/common/dac_common_all.c
@@ -0,0 +1,516 @@
+/** @addtogroup dac_file
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies
+
+@date 18 August 2012
+
+This library supports the Digital to Analog Conversion System in the
+STM32F series of ARM Cortex Microcontrollers by ST Microelectronics.
+
+The DAC is present only in a limited set of devices, notably some
+of the connection line, high density and XL devices.
+
+Two DAC channels are available, however unlike the ADC channels these
+are separate DAC devices controlled by the same register block.
+
+The DAC is on APB1. Its clock must be enabled in RCC and the GPIO
+ports set to alternate function output before it can be used.
+The digital output driver is disabled so the output driver mode
+(push-pull/open drain) is arbitrary.
+
+The DAC has a holding (buffer) register and an output register from
+which the analog output is derived. The holding register must be
+loaded first. If triggering is enabled the output register is loaded
+from the holding register after a trigger occurs. If triggering is
+not enabled the holding register contents are transferred directly
+to the output register.
+
+@note To avoid nonlinearities, do not allow outputs to range close
+to zero or V_analog.
+
+@section dac_api_dual Dual Channel Conversion
+
+There are dual modes in which both DACs are used to output data
+simultaneously or independently on both channels. The data must be
+presented according to the formats described in the datasheets. A
+convenience function @ref dac_load_data_buffer_dual is provided
+for software controlled use.
+
+A variety of modes are available depending on whether independent
+or simultaneous output is desired, and whether waveforms are to be
+superimposed. Refer to the datasheets.
+
+If DMA is used, only enable it for one of the channels. The DMA
+requests will then serve data in dual format to the data register
+dedicated to dual mode. The data will then be split and loaded to the
+appropriate DAC following the next trigger. There are three registers
+available, one for each of the formats: 12 bit right-aligned, 12 bit
+left-aligned and 8 bit right-aligned. The desired format is determined
+by specifying the appropriate register to the DMA controller.
+
+@section dac_api_basic_ex Basic DAC handling API.
+
+Set the DAC's GPIO port to any alternate function output mode. Enable the
+DAC clock. Enable the DAC, set a trigger source and load the buffer
+with the first value. After the DAC is triggered, load the buffer with
+the next value. This example uses software triggering and added noise.
+The trigger and further buffer load calls are made when data is to be
+sent out.
+
+@code
+ gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
+ GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO4);
+ rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_DACEN);
+ dac_disable(CHANNEL_1);
+ dac_set_waveform_characteristics(DAC_CR_MAMP1_8);
+ dac_set_waveform_generation(DAC_CR_WAVE1_NOISE);
+ dac_enable(CHANNEL_1);
+ dac_set_trigger_source(DAC_CR_TSEL1_SW);
+ dac_load_data_buffer_single(0, RIGHT12, CHANNEL_1);
+ ....
+ dac_software_trigger(CHANNEL_1);
+ dac_load_data_buffer_single(value, RIGHT12, CHANNEL_1);
+@endcode
+
+@section dac_api_dma_ex Simultaneous Dual DAC with DMA.
+
+This example in part sets up the DAC channel 1 DMA (DMA2 channel 3) to read
+16 bit data from memory into the right-aligned 8 bit dual register DAC_DHR8RD.
+Both DAC channels are enabled, and both triggers are set to the same timer
+2 input as required for simultaneous operation. DMA is enabled for DAC channel
+1 only to ensure that only one DMA request is generated.
+
+@code
+ dma_set_memory_size(DMA2,DMA_CHANNEL3,DMA_CCR_MSIZE_16BIT);
+ dma_set_peripheral_size(DMA2,DMA_CHANNEL3,DMA_CCR_PSIZE_16BIT);
+ dma_set_read_from_memory(DMA2,DMA_CHANNEL3);
+ dma_set_peripheral_address(DMA2,DMA_CHANNEL3,(u32) &DAC_DHR8RD);
+ dma_enable_channel(DMA2,DMA_CHANNEL3);
+ ...
+ dac_trigger_enable(CHANNEL_D);
+ dac_set_trigger_source(DAC_CR_TSEL1_T2 | DAC_CR_TSEL2_T2);
+ dac_dma_enable(CHANNEL_1);
+ dac_enable(CHANNEL_D);
+@endcode
+
+LGPL License Terms @ref lgpl_license
+ */
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 Ken Sarkies
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**@{*/
+
+#include <libopencm3/stm32/dac.h>
+
+#define MASK8 0xFF
+#define MASK12 0xFFF
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DAC Channel Enable.
+
+Enable a digital to analog converter channel. After setting this enable, the DAC
+requires a t<sub>wakeup</sub> time typically around 10 microseconds before it
+actually wakes up.
+
+@param[in] dac_channel enum ::data_channel.
+*/
+
+void dac_enable(data_channel dac_channel)
+{
+ switch (dac_channel) {
+ case CHANNEL_1:
+ DAC_CR |= DAC_CR_EN1;
+ break;
+ case CHANNEL_2:
+ DAC_CR |= DAC_CR_EN2;
+ break;
+ case CHANNEL_D:
+ DAC_CR |= (DAC_CR_EN1 | DAC_CR_EN2);
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DAC Channel Disable.
+
+Disable a digital to analog converter channel.
+
+@param[in] dac_channel enum ::data_channel.
+*/
+
+void dac_disable(data_channel dac_channel)
+{
+ switch (dac_channel) {
+ case CHANNEL_1:
+ DAC_CR &= ~DAC_CR_EN1;
+ break;
+ case CHANNEL_2:
+ DAC_CR &= ~DAC_CR_EN2;
+ break;
+ case CHANNEL_D:
+ DAC_CR &= ~(DAC_CR_EN1 | DAC_CR_EN2);
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DAC Channel Output Buffer Enable.
+
+Enable a digital to analog converter channel output drive buffer. This is an optional
+amplifying buffer that provides additional drive for the output signal. The
+buffer is enabled by default after a reset and needs to be explicitly disabled
+if required.
+
+@param[in] dac_channel enum ::data_channel.
+*/
+
+void dac_buffer_enable(data_channel dac_channel)
+{
+ switch (dac_channel) {
+ case CHANNEL_1:
+ DAC_CR |= DAC_CR_BOFF1;
+ break;
+ case CHANNEL_2:
+ DAC_CR |= DAC_CR_BOFF2;
+ break;
+ case CHANNEL_D:
+ DAC_CR |= (DAC_CR_BOFF1 | DAC_CR_BOFF2);
+ break;
+ }
+}
+/*-----------------------------------------------------------------------------*/
+/** @brief DAC Channel Output Buffer Disable.
+
+Disable a digital to analog converter channel output drive buffer. Disabling this will
+reduce power consumption slightly and will increase the output impedance of the DAC.
+The buffers are enabled by default after a reset.
+
+@param[in] dac_channel enum ::data_channel.
+*/
+
+void dac_buffer_disable(data_channel dac_channel)
+{
+ switch (dac_channel) {
+ case CHANNEL_1:
+ DAC_CR &= ~DAC_CR_BOFF1;
+ break;
+ case CHANNEL_2:
+ DAC_CR &= ~DAC_CR_BOFF2;
+ break;
+ case CHANNEL_D:
+ DAC_CR &= ~(DAC_CR_BOFF1 | DAC_CR_BOFF2);
+ break;
+ }
+}
+/*-----------------------------------------------------------------------------*/
+/** @brief DAC Channel DMA Enable.
+
+Enable a digital to analog converter channel DMA mode (connected to DMA2 channel
+3 for DAC channel 1 and DMA2 channel 4 for DAC channel 2). A DMA request is
+generated following an external trigger.
+
+@param[in] dac_channel enum ::data_channel.
+*/
+
+void dac_dma_enable(data_channel dac_channel)
+{
+ switch (dac_channel) {
+ case CHANNEL_1:
+ DAC_CR |= DAC_CR_DMAEN1;
+ break;
+ case CHANNEL_2:
+ DAC_CR |= DAC_CR_DMAEN2;
+ break;
+ case CHANNEL_D:
+ DAC_CR |= (DAC_CR_DMAEN1 | DAC_CR_DMAEN2);
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DAC Channel DMA Disable.
+
+Disable a digital to analog converter channel DMA mode.
+
+@param[in] dac_channel enum ::data_channel.
+*/
+
+void dac_dma_disable(data_channel dac_channel)
+{
+ switch (dac_channel) {
+ case CHANNEL_1:
+ DAC_CR &= ~DAC_CR_DMAEN1;
+ break;
+ case CHANNEL_2:
+ DAC_CR &= ~DAC_CR_DMAEN2;
+ break;
+ case CHANNEL_D:
+ DAC_CR &= ~(DAC_CR_DMAEN1 | DAC_CR_DMAEN2);
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DAC Channel Trigger Enable.
+
+Enable a digital to analog converter channel external trigger mode. This allows an
+external trigger to initiate register transfers from the buffer register to the DAC
+output register, followed by a DMA transfer to the buffer register if DMA is enabled.
+The trigger source must also be selected.
+
+@param[in] dac_channel enum ::data_channel.
+*/
+
+void dac_trigger_enable(data_channel dac_channel)
+{
+ switch (dac_channel) {
+ case CHANNEL_1:
+ DAC_CR |= DAC_CR_TEN1;
+ break;
+ case CHANNEL_2:
+ DAC_CR |= DAC_CR_TEN2;
+ break;
+ case CHANNEL_D:
+ DAC_CR |= (DAC_CR_TEN1 | DAC_CR_TEN2);
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DAC Channel Trigger Disable.
+
+Disable a digital to analog converter channel external trigger.
+
+@param[in] dac_channel enum ::data_channel.
+*/
+
+void dac_trigger_disable(data_channel dac_channel)
+{
+ switch (dac_channel) {
+ case CHANNEL_1:
+ DAC_CR &= ~DAC_CR_TEN1;
+ break;
+ case CHANNEL_2:
+ DAC_CR &= ~DAC_CR_TEN2;
+ break;
+ case CHANNEL_D:
+ DAC_CR &= ~(DAC_CR_TEN1 | DAC_CR_TEN2);
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Set DAC Channel Trigger Source.
+
+Sets the digital to analog converter trigger source, which can be taken from various
+timers, an external trigger or a software trigger.
+
+@param[in] dac_trig_src u32. Taken from @ref dac_trig2_sel or @ref dac_trig1_sel or
+a logical OR of one of each of these to set both channels simultaneously.
+*/
+
+void dac_set_trigger_source(u32 dac_trig_src)
+{
+ DAC_CR |= dac_trig_src;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Enable and Set DAC Channel Waveform Generation.
+
+Enable the digital to analog converter waveform generation as either pseudo-random
+noise or triangular wave. These signals are superimposed on existing output values
+in the DAC output registers.
+
+@note The DAC trigger must be enabled for this to work.
+
+@param[in] dac_wave_ens u32. Taken from @ref dac_wave1_en or @ref dac_wave2_en or
+a logical OR of one of each of these to set both channels simultaneously.
+*/
+
+void dac_set_waveform_generation(u32 dac_wave_ens)
+{
+ DAC_CR |= dac_wave_ens;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Disable DAC Channel Waveform Generation.
+
+Disable a digital to analog converter channel superimposed waveform generation.
+
+@param[in] dac_channel enum ::data_channel.
+*/
+
+void dac_disable_waveform_generation(data_channel dac_channel)
+{
+ switch (dac_channel) {
+ case CHANNEL_1:
+ DAC_CR &= ~DAC_CR_WAVE1_DIS;
+ break;
+ case CHANNEL_2:
+ DAC_CR &= ~DAC_CR_WAVE2_DIS;
+ break;
+ case CHANNEL_D:
+ DAC_CR &= ~(DAC_CR_WAVE1_DIS | DAC_CR_WAVE2_DIS);
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Set DAC Channel LFSR Mask or Triangle Wave Amplitude.
+
+Sets the digital to analog converter superimposed waveform generation characteristics.
+@li If the noise generation mode is set, this sets the length of the PRBS sequence and
+hence the amplitude of the output noise signal. Default setting is length 1.
+@li If the triangle wave generation mode is set, this sets the amplitude of the
+output signal as 2^(n)-1 where n is the parameter value. Default setting is 1.
+
+@note High amplitude levels of these waveforms can overload the DAC and distort the
+signal output.
+@note This must be called before enabling the DAC as the settings will then become read-only.
+@note The DAC trigger must be enabled for this to work.
+
+@param[in] dac_mamp u32. Taken from @ref dac_mamp2 or @ref dac_mamp1 or a logical OR
+of one of each of these to set both channels simultaneously.
+*/
+
+void dac_set_waveform_characteristics(u32 dac_mamp)
+{
+ DAC_CR |= dac_mamp;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Load DAC Data Register.
+
+Loads the appropriate digital to analog converter data register with 12 or 8 bit
+data to be converted on a channel. The data can be aligned as follows:
+@li right-aligned 8 bit data in bits 0-7
+@li right-aligned 12 bit data in bits 0-11
+@li left aligned 12 bit data in bits 4-15
+
+This function can also be used to load the dual channel registers if the data is
+formatted according to the datasheets:
+@li right-aligned 8 bit data in bits 0-7 for channel 1 and 8-15 for channel 2
+@li right-aligned 12 bit data in bits 0-11 for channel 1 and 16-27 for channel 2
+@li left aligned 12 bit data in bits 4-15 for channel 1 and 20-31 for channel 2
+
+@param[in] dac_data u32 with appropriate alignment.
+@param[in] dac_data_format enum ::data_align. Alignment and size.
+@param[in] dac_channel enum ::data_channel.
+*/
+
+void dac_load_data_buffer_single(u32 dac_data, data_align dac_data_format, data_channel dac_channel)
+{
+ if (dac_channel == CHANNEL_1)
+ {
+ switch (dac_data_format) {
+ case RIGHT8:
+ DAC_DHR8R1 = dac_data;
+ break;
+ case RIGHT12:
+ DAC_DHR12R1 = dac_data;
+ break;
+ case LEFT12:
+ DAC_DHR12L1 = dac_data;
+ break;
+ }
+ }
+ else if (dac_channel == CHANNEL_2)
+ {
+ switch (dac_data_format) {
+ case RIGHT8:
+ DAC_DHR8R2 = dac_data;
+ break;
+ case RIGHT12:
+ DAC_DHR12R2 = dac_data;
+ break;
+ case LEFT12:
+ DAC_DHR12L2 = dac_data;
+ break;
+ }
+ }
+ else
+ switch (dac_data_format) {
+ case RIGHT8:
+ DAC_DHR8RD = dac_data;
+ break;
+ case RIGHT12:
+ DAC_DHR12RD = dac_data;
+ break;
+ case LEFT12:
+ DAC_DHR12LD = dac_data;
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Load DAC Dual Data Register.
+
+Loads the appropriate digital to analog converter dual data register with 12 or
+8 bit data to be converted for both channels. This allows high bandwidth
+simultaneous or independent analog output. The data in both channels are aligned
+identically.
+
+@param[in] dac_data1 u32 for channel 1 with appropriate alignment.
+@param[in] dac_data2 u32 for channel 2 with appropriate alignment.
+@param[in] dac_data_format enum ::data_align. Right or left aligned, and 8 or 12 bit.
+*/
+
+void dac_load_data_buffer_dual(u32 dac_data1, u32 dac_data2, data_align dac_data_format)
+{
+ switch (dac_data_format) {
+ case RIGHT8:
+ DAC_DHR8RD = ((dac_data1 & MASK8) | ((dac_data2 & MASK8) << 8));
+ break;
+ case RIGHT12:
+ DAC_DHR12RD = ((dac_data1 & MASK12) | ((dac_data2 & MASK12) << 12));
+ break;
+ case LEFT12:
+ DAC_DHR12LD = ((dac_data1 & MASK12) | ((dac_data2 & MASK12) << 16));
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Trigger the DAC by a Software Trigger.
+
+If the trigger source is set to be a software trigger, cause a trigger to occur.
+The trigger is cleared by hardware after conversion.
+
+@param[in] dac_channel enum ::data_channel.
+*/
+
+void dac_software_trigger(data_channel dac_channel)
+{
+ switch (dac_channel) {
+ case CHANNEL_1:
+ DAC_SWTRIGR |= DAC_SWTRIGR_SWTRIG1;
+ break;
+ case CHANNEL_2:
+ DAC_SWTRIGR |= DAC_SWTRIGR_SWTRIG2;
+ break;
+ case CHANNEL_D:
+ DAC_SWTRIGR |= (DAC_SWTRIGR_SWTRIG1 | DAC_SWTRIGR_SWTRIG2);
+ break;
+ }
+}
+/**@}*/
+
diff --git a/lib/stm32/common/i2c_common_all.c b/lib/stm32/common/i2c_common_all.c
new file mode 100644
index 0000000..28ae199
--- /dev/null
+++ b/lib/stm32/common/i2c_common_all.c
@@ -0,0 +1,411 @@
+/** @addtogroup i2c_file
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
+@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
+
+@date 15 October 2012
+
+Devices can have up to two I2C peripherals. The peripherals support SMBus and
+PMBus variants.
+
+A peripheral begins after reset in Slave mode. To become a Master a start
+condition must be generated. The peripheral will remain in Master mode unless
+a multimaster contention is lost or a stop condition is generated.
+
+@todo all sorts of lovely stuff like DMA, Interrupts, SMBus variant, Status
+register access, Error conditions
+
+LGPL License Terms @ref lgpl_license
+ */
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/i2c.h>
+#include <libopencm3/stm32/rcc.h>
+
+/**@{*/
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Reset.
+
+The I2C peripheral and all its associated configuration registers are placed in the
+reset condition. The reset is effected via the RCC peripheral reset system.
+
+@param[in] i2c Unsigned int32. I2C peripheral identifier @ref i2c_reg_base.
+*/
+
+void i2c_reset(u32 i2c)
+{
+ switch (i2c) {
+ case I2C1:
+ rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST);
+ rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST);
+ break;
+ case I2C2:
+ rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C2RST);
+ rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C2RST);
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Peripheral Enable.
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+
+void i2c_peripheral_enable(u32 i2c)
+{
+ I2C_CR1(i2c) |= I2C_CR1_PE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Peripheral Disable.
+
+This must not be reset while in Master mode until a communication has finished.
+In Slave mode, the peripheral is disabled only after communication has ended.
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+
+void i2c_peripheral_disable(u32 i2c)
+{
+ I2C_CR1(i2c) &= ~I2C_CR1_PE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Send Start Condition.
+
+If in Master mode this will cause a restart condition to occur at the end of the
+current transmission. If in Slave mode, this will initiate a start condition
+when the current bus activity is completed.
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+
+void i2c_send_start(u32 i2c)
+{
+ I2C_CR1(i2c) |= I2C_CR1_START;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Send Stop Condition.
+
+After the current byte transfer this will initiate a stop condition if in Master
+mode, or simply release the bus if in Slave mode.
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+
+void i2c_send_stop(u32 i2c)
+{
+ I2C_CR1(i2c) |= I2C_CR1_STOP;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Clear Stop Flag.
+
+Clear the "Send Stop" flag in the I2C config register
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_clear_stop(u32 i2c)
+{
+ I2C_CR1(i2c) &= ~I2C_CR1_STOP;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Set the 7 bit Slave Address for the Peripheral.
+
+This sets an address for Slave mode operation, in 7 bit form.
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+@param[in] slave Unsigned int8. Slave address 0...127.
+*/
+
+void i2c_set_own_7bit_slave_address(u32 i2c, u8 slave)
+{
+ I2C_OAR1(i2c) = (u16)(slave << 1);
+ I2C_OAR1(i2c) &= ~I2C_OAR1_ADDMODE;
+ I2C_OAR1(i2c) |= (1 << 14); /* Datasheet: always keep 1 by software. */
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Set the 10 bit Slave Address for the Peripheral.
+
+This sets an address for Slave mode operation, in 10 bit form.
+
+@todo add "I2C_OAR1(i2c) |= (1 << 14);" as above
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+@param[in] slave Unsigned int16. Slave address 0...1023.
+*/
+
+void i2c_set_own_10bit_slave_address(u32 i2c, u16 slave)
+{
+ I2C_OAR1(i2c) = (u16)(I2C_OAR1_ADDMODE | slave);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Set Fast Mode.
+
+Set the clock frequency to the high clock rate mode (up to 400kHz). The actual
+clock frequency must be set with @ref i2c_set_clock_frequency
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+
+void i2c_set_fast_mode(u32 i2c)
+{
+ I2C_CCR(i2c) |= I2C_CCR_FS;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Set Standard Mode.
+
+Set the clock frequency to the standard clock rate mode (up to 100kHz). The actual
+clock frequency must be set with @ref i2c_set_clock_frequency
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+
+void i2c_set_standard_mode(u32 i2c)
+{
+ I2C_CCR(i2c) &= ~I2C_CCR_FS;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Set Peripheral Clock Frequency.
+
+Set the peripheral clock frequency: 2MHz to 36MHz (the APB frequency). Note that
+this is <b> not </b> the I2C bus clock. This is set in conjunction with the Clock
+Control register to generate the Master bus clock, see @ref i2c_set_ccr
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+@param[in] freq Unsigned int8. Clock Frequency Setting @ref i2c_clock.
+*/
+
+void i2c_set_clock_frequency(u32 i2c, u8 freq)
+{
+ u16 reg16;
+ reg16 = I2C_CR2(i2c) & 0xffc0; /* Clear bits [5:0]. */
+ reg16 |= freq;
+ I2C_CR2(i2c) = reg16;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Set Bus Clock Frequency.
+
+Set the bus clock frequency. This is a 12 bit number (0...4095) calculated
+from the formulae given in the STM32F1 reference manual in the description
+of the CCR field. It is a divisor of the peripheral clock frequency
+@ref i2c_set_clock_frequency modified by the fast mode setting
+@ref i2c_set_fast_mode
+
+@todo provide additional API assitance to set the clock, eg macros
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+@param[in] freq Unsigned int16. Bus Clock Frequency Setting 0...4095.
+*/
+
+void i2c_set_ccr(u32 i2c, u16 freq)
+{
+ u16 reg16;
+ reg16 = I2C_CCR(i2c) & 0xf000; /* Clear bits [11:0]. */
+ reg16 |= freq;
+ I2C_CCR(i2c) = reg16;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Set the Rise Time.
+
+Set the maximum rise time on the bus according to the I2C specification, as 1
+more than the specified rise time in peripheral clock cycles. This is a 6 bit
+number.
+
+@todo provide additional APIP assistance.
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+@param[in] trise Unsigned int16. Rise Time Setting 0...63.
+*/
+
+void i2c_set_trise(u32 i2c, u16 trise)
+{
+ I2C_TRISE(i2c) = trise;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Send the 7-bit Slave Address.
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+@param[in] slave Unsigned int16. Slave address 0...1023.
+@param[in] readwrite Unsigned int8. Single bit to instruct slave to receive or send @ref i2c_rw.
+*/
+
+void i2c_send_7bit_address(u32 i2c, u8 slave, u8 readwrite)
+{
+ I2C_DR(i2c) = (u8)((slave << 1) | readwrite);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Send Data.
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+@param[in] data Unsigned int8. Byte to send.
+*/
+
+void i2c_send_data(u32 i2c, u8 data)
+{
+ I2C_DR(i2c) = data;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Get Data.
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+uint8_t i2c_get_data(u32 i2c)
+{
+ return I2C_DR(i2c) & 0xff;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Enable Interrupt
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+@param[in] interrupt Unsigned int32. Interrupt to enable.
+*/
+void i2c_enable_interrupt(u32 i2c, u32 interrupt)
+{
+ I2C_CR2(i2c) |= interrupt;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Disable Interrupt
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+@param[in] interrupt Unsigned int32. Interrupt to disable.
+*/
+void i2c_disable_interrupt(u32 i2c, u32 interrupt)
+{
+ I2C_CR2(i2c) &= ~interrupt;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Enable ACK
+
+Enables acking of own 7/10 bit address
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_enable_ack(u32 i2c)
+{
+ I2C_CR1(i2c) |= I2C_CR1_ACK;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Disable ACK
+
+Disables acking of own 7/10 bit address
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_disable_ack(u32 i2c)
+{
+ I2C_CR1(i2c) &= ~I2C_CR1_ACK;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C NACK Next Byte
+
+Causes the I2C controller to NACK the reception of the next byte
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_nack_next(u32 i2c)
+{
+ I2C_CR1(i2c) |= I2C_CR1_POS;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C NACK Next Byte
+
+Causes the I2C controller to NACK the reception of the current byte
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_nack_current(u32 i2c)
+{
+ I2C_CR1(i2c) &= ~I2C_CR1_POS;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Set clock duty cycle
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+@param[in] dutycycle Unsigned int32. I2C duty cycle @ref i2c_duty_cycle.
+*/
+void i2c_set_dutycycle(u32 i2c, u32 dutycycle)
+{
+ if (dutycycle == I2C_CCR_DUTY_DIV2)
+ I2C_CCR(i2c) &= ~I2C_CCR_DUTY;
+ else
+ I2C_CCR(i2c) |= I2C_CCR_DUTY;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Enable DMA
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_enable_dma(u32 i2c)
+{
+ I2C_CR2(i2c) |= I2C_CR2_DMAEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Disable DMA
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_disable_dma(u32 i2c)
+{
+ I2C_CR2(i2c) &= ~I2C_CR2_DMAEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Set DMA last transfer
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_set_dma_last_transfer(u32 i2c)
+{
+ I2C_CR2(i2c) |= I2C_CR2_LAST;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Clear DMA last transfer
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_clear_dma_last_transfer(u32 i2c)
+{
+ I2C_CR2(i2c) &= ~I2C_CR2_LAST;
+}
+
+/**@}*/
diff --git a/lib/stm32/common/iwdg_common_all.c b/lib/stm32/common/iwdg_common_all.c
new file mode 100644
index 0000000..d3d9364
--- /dev/null
+++ b/lib/stm32/common/iwdg_common_all.c
@@ -0,0 +1,140 @@
+/** @addtogroup iwdg_file
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies ksarkies@internode.on.net
+
+@date 18 August 2012
+
+This library supports the Independent Watchdog Timer System in the STM32F1xx
+series of ARM Cortex Microcontrollers by ST Microelectronics.
+
+The watchdog timer uses the LSI (low speed internal) clock which is low power
+and continues to operate during stop and standby modes. Its frequency is
+nominally 32kHz (40kHz for the STM32F1xx series) but can vary from as low
+as 17kHz up to 60kHz (refer to datasheet electrical characteristics).
+
+Note that the User Configuration option byte provides a means of automatically
+enabling the IWDG timer at power on (with counter value 0xFFF). If the
+relevant bit is not set, the IWDG timer must be enabled by software.
+
+@note: Tested: CPU STM32F103RET6, Board ET-ARM Stamp STM32
+
+LGPL License Terms @ref lgpl_license
+ */
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**@{*/
+
+#include <libopencm3/stm32/iwdg.h>
+
+#define LSI_FREQUENCY 32000
+#define COUNT_LENGTH 12
+#define COUNT_MASK ((1 << COUNT_LENGTH)-1)
+
+/*-----------------------------------------------------------------------------*/
+/** @brief IWDG Enable Watchdog Timer
+
+The watchdog timer is started. The timeout period defaults to 512 milliseconds
+unless it has been previously defined.
+
+*/
+
+void iwdg_start(void)
+{
+ IWDG_KR = IWDG_KR_START;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief IWDG Set Period in Milliseconds
+
+The countdown period is converted into count and prescale values. The maximum
+period is 32.76 seconds; values above this are truncated. Periods less than 1ms
+are not supported by this library.
+
+A delay of up to 5 clock cycles of the LSI clock (about 156 microseconds)
+can occasionally occur if the prescale or preload registers are currently busy
+loading a previous value.
+
+@param[in] period u32 Period in milliseconds (< 32760) from a watchdog reset until
+a system reset is issued.
+*/
+
+void iwdg_set_period_ms(u32 period)
+{
+u32 count, prescale, reload, exponent;
+/* Set the count to represent ticks of the 32kHz LSI clock */
+ count = (period << 5);
+/* Strip off the first 12 bits to get the prescale value required */
+ prescale = (count >> 12);
+ if (prescale > 256) {exponent = IWDG_PR_DIV256; reload = COUNT_MASK;}
+ else if (prescale > 128) {exponent = IWDG_PR_DIV256; reload = (count >> 8);}
+ else if (prescale > 64) {exponent = IWDG_PR_DIV128; reload = (count >> 7);}
+ else if (prescale > 32) {exponent = IWDG_PR_DIV64; reload = (count >> 6);}
+ else if (prescale > 16) {exponent = IWDG_PR_DIV32; reload = (count >> 5);}
+ else if (prescale > 8) {exponent = IWDG_PR_DIV16; reload = (count >> 4);}
+ else if (prescale > 4) {exponent = IWDG_PR_DIV8; reload = (count >> 3);}
+ else {exponent = IWDG_PR_DIV4; reload = (count >> 2);}
+/* Avoid the undefined situation of a zero count */
+ if (count == 0) count = 1;
+
+ while (iwdg_prescaler_busy());
+ IWDG_KR = IWDG_KR_UNLOCK;
+ IWDG_PR = exponent;
+ while (iwdg_reload_busy());
+ IWDG_KR = IWDG_KR_UNLOCK;
+ IWDG_RLR = (reload & COUNT_MASK);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief IWDG Get Reload Register Status
+
+@returns boolean: TRUE if the reload register is busy and unavailable for loading
+a new count value.
+*/
+
+bool iwdg_reload_busy(void)
+{
+ return (IWDG_SR & IWDG_SR_RVU);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief IWDG Get Prescaler Register Status
+
+@returns boolean: TRUE if the prescaler register is busy and unavailable for loading
+a new period value.
+*/
+
+bool iwdg_prescaler_busy(void)
+{
+ return (IWDG_SR & IWDG_SR_PVU);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief IWDG reset Watchdog Timer
+
+The watchdog timer is reset. The counter restarts from the value in the reload
+register.
+*/
+
+void iwdg_reset(void)
+{
+ IWDG_KR = IWDG_KR_RESET;
+}
+/**@}*/
+
diff --git a/lib/stm32/common/spi_common_all.c b/lib/stm32/common/spi_common_all.c
new file mode 100644
index 0000000..2e6473d
--- /dev/null
+++ b/lib/stm32/common/spi_common_all.c
@@ -0,0 +1,727 @@
+/** @addtogroup spi_file
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
+@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
+
+@date 15 October 2012
+
+Devices can have up to three SPI peripherals. The common 4-wire full-duplex
+mode of operation is supported, along with 3-wire variants using unidirectional
+communication modes or half-duplex bidirectional communication. A variety of
+options allows many of the SPI variants to be supported. Multimaster operation
+is also supported. A CRC can be generated and checked in hardware.
+
+@note Some JTAG pins need to be remapped if SPI is to be used.
+
+@note The I2S protocol shares the SPI hardware so the two protocols cannot be
+used at the same time on the same peripheral.
+
+Example: 1Mbps, positive clock polarity, leading edge trigger, 8-bit words,
+LSB first.
+@code
+ spi_init_master(SPI1, 1000000, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE,
+ SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_8BIT,
+ SPI_CR1_LSBFIRST);
+ spi_write(SPI1, 0x55); // 8-bit write
+ spi_write(SPI1, 0xaa88); // 16-bit write
+ reg8 = spi_read(SPI1); // 8-bit read
+ reg16 = spi_read(SPI1); // 16-bit read
+@endcode
+
+@todo need additional functions to aid ISRs in retrieving status
+
+LGPL License Terms @ref lgpl_license
+ */
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/spi.h>
+#include <libopencm3/stm32/rcc.h>
+
+/*
+ * SPI and I2S code.
+ *
+ * Examples:
+ * spi_init_master(SPI1, 1000000, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE,
+ * SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_8BIT,
+ * SPI_CR1_LSBFIRST);
+ * spi_write(SPI1, 0x55); // 8-bit write
+ * spi_write(SPI1, 0xaa88); // 16-bit write
+ * reg8 = spi_read(SPI1); // 8-bit read
+ * reg16 = spi_read(SPI1); // 16-bit read
+ */
+
+/**@{*/
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Reset.
+
+The SPI peripheral and all its associated configuration registers are placed in the
+reset condition. The reset is effected via the RCC peripheral reset system.
+
+@param[in] spi_peripheral Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_reset(u32 spi_peripheral)
+{
+ switch (spi_peripheral) {
+ case SPI1:
+ rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_SPI1RST);
+ rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_SPI1RST);
+ break;
+ case SPI2:
+ rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI2RST);
+ rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI2RST);
+ break;
+#if defined(STM32F1) || defined(STM32F2) || defined(STM32F3) || defined(STM32F4)
+ case SPI3:
+ rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI3RST);
+ rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI3RST);
+ break;
+#endif
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Configure the SPI as Master.
+
+The SPI peripheral is configured as a master with communication parameters
+baudrate, data format 8/16 bits, frame format lsb/msb first, clock polarity
+and phase. The SPI enable, CRC enable and CRC next controls are not affected.
+These must be controlled separately.
+
+@todo NSS pin handling.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+@param[in] br Unsigned int32. Baudrate @ref spi_baudrate.
+@param[in] cpol Unsigned int32. Clock polarity @ref spi_cpol.
+@param[in] cpha Unsigned int32. Clock Phase @ref spi_cpha.
+@param[in] dff Unsigned int32. Data frame format 8/16 bits @ref spi_dff.
+@param[in] lsbfirst Unsigned int32. Frame format lsb/msb first @ref spi_lsbfirst.
+@returns int. Error code.
+*/
+
+int spi_init_master(u32 spi, u32 br, u32 cpol, u32 cpha, u32 dff, u32 lsbfirst)
+{
+ u32 reg32 = SPI_CR1(spi);
+
+ /* Reset all bits omitting SPE, CRCEN and CRCNEXT bits. */
+ reg32 &= SPI_CR1_SPE | SPI_CR1_CRCEN | SPI_CR1_CRCNEXT;
+
+ reg32 |= SPI_CR1_MSTR; /* Configure SPI as master. */
+
+ reg32 |= br; /* Set baud rate bits. */
+ reg32 |= cpol; /* Set CPOL value. */
+ reg32 |= cpha; /* Set CPHA value. */
+ reg32 |= dff; /* Set data format (8 or 16 bits). */
+ reg32 |= lsbfirst; /* Set frame format (LSB- or MSB-first). */
+
+ /* TODO: NSS pin handling. */
+
+ SPI_CR1(spi) = reg32;
+
+ return 0; /* TODO */
+}
+
+/* TODO: Error handling? */
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Enable.
+
+The SPI peripheral is enabled.
+
+@todo Error handling?
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_enable(u32 spi)
+{
+ SPI_CR1(spi) |= SPI_CR1_SPE; /* Enable SPI. */
+}
+
+/* TODO: Error handling? */
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Disable.
+
+The SPI peripheral is disabled.
+
+@todo Follow procedure from section 23.3.8 in the TRM.
+(possibly create a "clean disable" function separately)
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_disable(u32 spi)
+{
+ u32 reg32;
+
+ reg32 = SPI_CR1(spi);
+ reg32 &= ~(SPI_CR1_SPE); /* Disable SPI. */
+ SPI_CR1(spi) = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Data Write.
+
+Data is written to the SPI interface.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+@param[in] data Unsigned int16. 8 or 16 bit data to be written.
+*/
+
+void spi_write(u32 spi, u16 data)
+{
+ /* Write data (8 or 16 bits, depending on DFF) into DR. */
+ SPI_DR(spi) = data;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Data Write with Blocking.
+
+Data is written to the SPI interface after the previous write transfer has finished.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+@param[in] data Unsigned int16. 8 or 16 bit data to be written.
+*/
+
+void spi_send(u32 spi, u16 data)
+{
+ /* Wait for transfer finished. */
+ while (!(SPI_SR(spi) & SPI_SR_TXE))
+ ;
+
+ /* Write data (8 or 16 bits, depending on DFF) into DR. */
+ SPI_DR(spi) = data;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Data Read.
+
+Data is read from the SPI interface after the incoming transfer has finished.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+@returns data Unsigned int16. 8 or 16 bit data.
+*/
+
+u16 spi_read(u32 spi)
+{
+ /* Wait for transfer finished. */
+ while (!(SPI_SR(spi) & SPI_SR_RXNE))
+ ;
+
+ /* Read the data (8 or 16 bits, depending on DFF bit) from DR. */
+ return SPI_DR(spi);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Data Write and Read Exchange.
+
+Data is written to the SPI interface, then a read is done after the incoming transfer
+has finished.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+@param[in] data Unsigned int16. 8 or 16 bit data to be written.
+@returns data Unsigned int16. 8 or 16 bit data.
+*/
+
+u16 spi_xfer(u32 spi, u16 data)
+{
+ spi_write(spi, data);
+
+ /* Wait for transfer finished. */
+ while (!(SPI_SR(spi) & SPI_SR_RXNE))
+ ;
+
+ /* Read the data (8 or 16 bits, depending on DFF bit) from DR. */
+ return SPI_DR(spi);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set Bidirectional Simplex Mode.
+
+The SPI peripheral is set for bidirectional transfers in two-wire simplex mode
+(using a clock wire and a bidirectional data wire).
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_bidirectional_mode(u32 spi)
+{
+ SPI_CR1(spi) |= SPI_CR1_BIDIMODE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set Unidirectional Mode.
+
+The SPI peripheral is set for unidirectional transfers. This is used in full duplex
+mode or when the SPI is placed in two-wire simplex mode that uses a clock wire and a
+unidirectional data wire.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_unidirectional_mode(u32 spi)
+{
+ SPI_CR1(spi) &= ~SPI_CR1_BIDIMODE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set Bidirectional Simplex Receive Only Mode.
+
+The SPI peripheral is set for bidirectional transfers in two-wire simplex mode
+(using a clock wire and a bidirectional data wire), and is placed in a receive state.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_bidirectional_receive_only_mode(u32 spi)
+{
+ SPI_CR1(spi) |= SPI_CR1_BIDIMODE;
+ SPI_CR1(spi) &= ~SPI_CR1_BIDIOE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set Bidirectional Simplex Receive Only Mode.
+
+The SPI peripheral is set for bidirectional transfers in two-wire simplex mode
+(using a clock wire and a bidirectional data wire), and is placed in a transmit state.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_bidirectional_transmit_only_mode(u32 spi)
+{
+ SPI_CR1(spi) |= SPI_CR1_BIDIMODE;
+ SPI_CR1(spi) |= SPI_CR1_BIDIOE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Enable the CRC.
+
+The SPI peripheral is set to use a CRC field for transmit and receive.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_enable_crc(u32 spi)
+{
+ SPI_CR1(spi) |= SPI_CR1_CRCEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Disable the CRC.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_disable_crc(u32 spi)
+{
+ SPI_CR1(spi) &= ~SPI_CR1_CRCEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Next Transmit is a Data Word
+
+The next transmission to take place is a data word from the transmit buffer.
+This must be called before transmission to distinguish between sending
+of a data or CRC word.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_next_tx_from_buffer(u32 spi)
+{
+ SPI_CR1(spi) &= ~SPI_CR1_CRCNEXT;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Next Transmit is a CRC Word
+
+The next transmission to take place is a crc word from the hardware crc unit.
+This must be called before transmission to distinguish between sending
+of a data or CRC word.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_next_tx_from_crc(u32 spi)
+{
+ SPI_CR1(spi) |= SPI_CR1_CRCNEXT;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set Data Frame Format to 8 bits
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_dff_8bit(u32 spi)
+{
+ SPI_CR1(spi) &= ~SPI_CR1_DFF;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set Data Frame Format to 16 bits
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_dff_16bit(u32 spi)
+{
+ SPI_CR1(spi) |= SPI_CR1_DFF;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set Full Duplex (3-wire) Mode
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_full_duplex_mode(u32 spi)
+{
+ SPI_CR1(spi) &= ~SPI_CR1_RXONLY;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set Receive Only Mode for Simplex (2-wire) Unidirectional Transfers
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_receive_only_mode(u32 spi)
+{
+ SPI_CR1(spi) |= SPI_CR1_RXONLY;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Enable Slave Management by Hardware
+
+In slave mode the NSS hardware input is used as a select enable for the slave.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_disable_software_slave_management(u32 spi)
+{
+ SPI_CR1(spi) &= ~SPI_CR1_SSM;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Enable Slave Management by Software
+
+In slave mode the NSS hardware input is replaced by an internal software
+enable/disable of the slave (@ref spi_set_nss_high).
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_enable_software_slave_management(u32 spi)
+{
+ SPI_CR1(spi) |= SPI_CR1_SSM;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set the Software NSS Signal High
+
+In slave mode, and only when software slave management is used, this replaces
+the NSS signal with a slave select enable signal.
+
+@todo these should perhaps be combined with an SSM enable as it is meaningless otherwise
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_nss_high(u32 spi)
+{
+ SPI_CR1(spi) |= SPI_CR1_SSI;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set the Software NSS Signal Low
+
+In slave mode, and only when software slave management is used, this replaces
+the NSS signal with a slave select disable signal.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_nss_low(u32 spi)
+{
+ SPI_CR1(spi) &= ~SPI_CR1_SSI;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set to Send LSB First
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_send_lsb_first(u32 spi)
+{
+ SPI_CR1(spi) |= SPI_CR1_LSBFIRST;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set to Send MSB First
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_send_msb_first(u32 spi)
+{
+ SPI_CR1(spi) &= ~SPI_CR1_LSBFIRST;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set the Baudrate Prescaler
+
+@todo Why is this specification different to the spi_init_master baudrate values?
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+@param[in] baudrate Unsigned int8. Baudrate prescale value @ref spi_br_pre.
+*/
+
+void spi_set_baudrate_prescaler(u32 spi, u8 baudrate)
+{
+ u32 reg32;
+
+ if (baudrate > 7)
+ return;
+
+ reg32 = (SPI_CR1(spi) & 0xffc7); /* Clear bits [5:3]. */
+ reg32 |= (baudrate << 3);
+ SPI_CR1(spi) = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set to Master Mode
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_master_mode(u32 spi)
+{
+ SPI_CR1(spi) |= SPI_CR1_MSTR;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set to Slave Mode
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_slave_mode(u32 spi)
+{
+ SPI_CR1(spi) &= ~SPI_CR1_MSTR;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set the Clock Polarity to High when Idle
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_clock_polarity_1(u32 spi)
+{
+ SPI_CR1(spi) |= SPI_CR1_CPOL;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set the Clock Polarity to Low when Idle
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_clock_polarity_0(u32 spi)
+{
+ SPI_CR1(spi) &= ~SPI_CR1_CPOL;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set the Clock Phase to Capture on Trailing Edge
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_clock_phase_1(u32 spi)
+{
+ SPI_CR1(spi) |= SPI_CR1_CPHA;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set the Clock Phase to Capture on Leading Edge
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_set_clock_phase_0(u32 spi)
+{
+ SPI_CR1(spi) &= ~SPI_CR1_CPHA;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Enable the Transmit Buffer Empty Interrupt
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_enable_tx_buffer_empty_interrupt(u32 spi)
+{
+ SPI_CR2(spi) |= SPI_CR2_TXEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Disable the Transmit Buffer Empty Interrupt
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_disable_tx_buffer_empty_interrupt(u32 spi)
+{
+ SPI_CR2(spi) &= ~SPI_CR2_TXEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Enable the Receive Buffer Ready Interrupt
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_enable_rx_buffer_not_empty_interrupt(u32 spi)
+{
+ SPI_CR2(spi) |= SPI_CR2_RXNEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Disable the Receive Buffer Ready Interrupt
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_disable_rx_buffer_not_empty_interrupt(u32 spi)
+{
+ SPI_CR2(spi) &= ~SPI_CR2_RXNEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Enable the Error Interrupt
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_enable_error_interrupt(u32 spi)
+{
+ SPI_CR2(spi) |= SPI_CR2_ERRIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Disable the Error Interrupt
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_disable_error_interrupt(u32 spi)
+{
+ SPI_CR2(spi) &= ~SPI_CR2_ERRIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set the NSS Pin as an Output
+
+Normally used in master mode to allows the master to place all devices on the
+SPI bus into slave mode. Multimaster mode is not possible.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_enable_ss_output(u32 spi)
+{
+ SPI_CR2(spi) |= SPI_CR2_SSOE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Set the NSS Pin as an Input
+
+In master mode this allows the master to sense the presence of other masters. If
+NSS is then pulled low the master is placed into slave mode. In slave mode NSS
+becomes a slave enable.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_disable_ss_output(u32 spi)
+{
+ SPI_CR2(spi) &= ~SPI_CR2_SSOE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Enable Transmit Transfers via DMA
+
+This allows transmissions to proceed unattended using DMA to move data to the
+transmit buffer as it becomes available. The DMA channels provided for each
+SPI peripheral are given in the Technical Manual DMA section.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_enable_tx_dma(u32 spi)
+{
+ SPI_CR2(spi) |= SPI_CR2_TXDMAEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Disable Transmit Transfers via DMA
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_disable_tx_dma(u32 spi)
+{
+ SPI_CR2(spi) &= ~SPI_CR2_TXDMAEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Enable Receive Transfers via DMA
+
+This allows received data streams to proceed unattended using DMA to move data from
+the receive buffer as data becomes available. The DMA channels provided for each
+SPI peripheral are given in the Technical Manual DMA section.
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_enable_rx_dma(u32 spi)
+{
+ SPI_CR2(spi) |= SPI_CR2_RXDMAEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SPI Disable Receive Transfers via DMA
+
+@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
+*/
+
+void spi_disable_rx_dma(u32 spi)
+{
+ SPI_CR2(spi) &= ~SPI_CR2_RXDMAEN;
+}
+
+/**@}*/
diff --git a/lib/stm32/common/usart_common_all.c b/lib/stm32/common/usart_common_all.c
new file mode 100644
index 0000000..0c3d302
--- /dev/null
+++ b/lib/stm32/common/usart_common_all.c
@@ -0,0 +1,452 @@
+/** @addtogroup usart_file
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
+
+@date 30 August 2012
+
+This library supports the USART/UART in the STM32F series
+of ARM Cortex Microcontrollers by ST Microelectronics.
+
+Devices can have up to 3 USARTs and 2 UARTs.
+
+LGPL License Terms @ref lgpl_license
+ */
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**@{*/
+
+#include <libopencm3/stm32/usart.h>
+#include <libopencm3/stm32/rcc.h>
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Set Baudrate.
+
+The baud rate is computed from the APB high-speed prescaler clock (for USART1)
+or the APB low-speed prescaler clock (for other USARTs). These values must
+be correctly set before calling this function (refer to the rcc_clock_setup-*
+functions in RCC).
+
+@todo Add support for USART6 and oversampling in F2/F4
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+@param[in] baud unsigned 32 bit. Baud rate specified in Hz.
+*/
+
+void usart_set_baudrate(u32 usart, u32 baud)
+{
+ u32 clock = rcc_ppre1_frequency;
+
+//#ifdef STM32F1
+ if (usart == USART1) {
+ clock = rcc_ppre2_frequency;
+ }
+/* This has to be added for F2 when it get's support for USART6 */
+/*
+#else
+ if ((usart == USART1) ||
+ (usart == USART6)) {
+ clock = rcc_ppre2_frequency;
+ }
+#endif
+*/
+
+ /*
+ * Yes it is as simple as that. The reference manual is
+ * talking about fractional calculation but it seems to be only
+ * marketting babble to sound awesome. It is nothing else but a
+ * simple divider to generate the correct baudrate.
+ *
+ * Note: We round() the value rather than floor()ing it, for more
+ * accurate divisor selection.
+ */
+ USART_BRR(usart) = ((2 * clock) + baud) / (2 * baud);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Set Word Length.
+
+The word length is set to 8 or 9 bits. Note that the last bit will be a parity bit
+if parity is enabled, in which case the data length will be 7 or 8 bits respectively.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+@param[in] bits unsigned 32 bit. Word length in bits 8 or 9.
+*/
+
+void usart_set_databits(u32 usart, u32 bits)
+{
+ if (bits == 8)
+ USART_CR1(usart) &= ~USART_CR1_M; /* 8 data bits */
+ else
+ USART_CR1(usart) |= USART_CR1_M; /* 9 data bits */
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Set Stop Bit(s).
+
+The stop bits are specified as 0.5, 1, 1.5 or 2.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+@param[in] stopbits unsigned 32 bit. Stop bits @ref usart_cr2_stopbits.
+*/
+
+void usart_set_stopbits(u32 usart, u32 stopbits)
+{
+ u32 reg32;
+
+ reg32 = USART_CR2(usart);
+ reg32 = (reg32 & ~USART_CR2_STOPBITS_MASK) | stopbits;
+ USART_CR2(usart) = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Set Parity.
+
+The parity bit can be selected as none, even or odd.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+@param[in] parity unsigned 32 bit. Parity @ref usart_cr1_parity.
+*/
+
+void usart_set_parity(u32 usart, u32 parity)
+{
+ u32 reg32;
+
+ reg32 = USART_CR1(usart);
+ reg32 = (reg32 & ~USART_PARITY_MASK) | parity;
+ USART_CR1(usart) = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Set Rx/Tx Mode.
+
+The mode can be selected as Rx only, Tx only or Rx+Tx.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+@param[in] mode unsigned 32 bit. Mode @ref usart_cr1_mode.
+*/
+
+void usart_set_mode(u32 usart, u32 mode)
+{
+ u32 reg32;
+
+ reg32 = USART_CR1(usart);
+ reg32 = (reg32 & ~USART_MODE_MASK) | mode;
+ USART_CR1(usart) = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Set Hardware Flow Control.
+
+The flow control bit can be selected as none, RTS, CTS or RTS+CTS.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+@param[in] flowcontrol unsigned 32 bit. Flowcontrol @ref usart_cr3_flowcontrol.
+*/
+
+void usart_set_flow_control(u32 usart, u32 flowcontrol)
+{
+ u32 reg32;
+
+ reg32 = USART_CR3(usart);
+ reg32 = (reg32 & ~USART_FLOWCONTROL_MASK) | flowcontrol;
+ USART_CR3(usart) = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Enable.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_enable(u32 usart)
+{
+ USART_CR1(usart) |= USART_CR1_UE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Disable.
+
+At the end of the current frame, the USART is disabled to reduce power.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_disable(u32 usart)
+{
+ USART_CR1(usart) &= ~USART_CR1_UE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Send a Data Word.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+@param[in] data unsigned 16 bit.
+*/
+
+void usart_send(u32 usart, u16 data)
+{
+ /* Send data. */
+ USART_DR(usart) = (data & USART_DR_MASK);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Read a Received Data Word.
+
+If parity is enabled the MSB (bit 7 or 8 depending on the word length) is the parity bit.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+@returns unsigned 16 bit data word.
+*/
+
+u16 usart_recv(u32 usart)
+{
+ /* Receive data. */
+ return USART_DR(usart) & USART_DR_MASK;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Wait for Transmit Data Buffer Empty
+
+Blocks until the transmit data buffer becomes empty and is ready to accept the
+next data word.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_wait_send_ready(u32 usart)
+{
+ /* Wait until the data has been transferred into the shift register. */
+ while ((USART_SR(usart) & USART_SR_TXE) == 0);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Wait for Received Data Available
+
+Blocks until the receive data buffer holds a valid received data word.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_wait_recv_ready(u32 usart)
+{
+ /* Wait until the data is ready to be received. */
+ while ((USART_SR(usart) & USART_SR_RXNE) == 0);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Send Data Word with Blocking
+
+Blocks until the transmit data buffer becomes empty then writes the next data word
+for transmission.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+@param[in] data unsigned 16 bit.
+*/
+
+void usart_send_blocking(u32 usart, u16 data)
+{
+ usart_wait_send_ready(usart);
+ usart_send(usart, data);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Read a Received Data Word with Blocking.
+
+Wait until a data word has been received then return the word.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+@returns unsigned 16 bit data word.
+*/
+
+u16 usart_recv_blocking(u32 usart)
+{
+ usart_wait_recv_ready(usart);
+
+ return usart_recv(usart);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Receiver DMA Enable.
+
+DMA is available on:
+@li USART1 Rx DMA1 channel 5.
+@li USART2 Rx DMA1 channel 6.
+@li USART3 Rx DMA1 channel 3.
+@li UART4 Rx DMA2 channel 3.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_enable_rx_dma(u32 usart)
+{
+ USART_CR3(usart) |= USART_CR3_DMAR;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Receiver DMA Disable.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_disable_rx_dma(u32 usart)
+{
+ USART_CR3(usart) &= ~USART_CR3_DMAR;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Transmitter DMA Enable.
+
+DMA is available on:
+@li USART1 Tx DMA1 channel 4.
+@li USART2 Tx DMA1 channel 7.
+@li USART3 Tx DMA1 channel 2.
+@li UART4 Tx DMA2 channel 5.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_enable_tx_dma(u32 usart)
+{
+ USART_CR3(usart) |= USART_CR3_DMAT;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Transmitter DMA Disable.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_disable_tx_dma(u32 usart)
+{
+ USART_CR3(usart) &= ~USART_CR3_DMAT;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Receiver Interrupt Enable.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_enable_rx_interrupt(u32 usart)
+{
+ USART_CR1(usart) |= USART_CR1_RXNEIE;
+}
+
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Receiver Interrupt Disable.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_disable_rx_interrupt(u32 usart)
+{
+ USART_CR1(usart) &= ~USART_CR1_RXNEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Transmitter Interrupt Enable.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_enable_tx_interrupt(u32 usart)
+{
+ USART_CR1(usart) |= USART_CR1_TXEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Transmitter Interrupt Disable.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_disable_tx_interrupt(u32 usart)
+{
+ USART_CR1(usart) &= ~USART_CR1_TXEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Error Interrupt Enable.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_enable_error_interrupt(u32 usart)
+{
+ USART_CR3(usart) |= USART_CR3_EIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Error Interrupt Disable.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_disable_error_interrupt(u32 usart)
+{
+ USART_CR3(usart) &= ~USART_CR3_EIE;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief USART Read a Status Flag.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+@param[in] flag Unsigned int32. Status register flag @ref usart_sr_flags.
+@returns boolean: flag set.
+*/
+
+bool usart_get_flag(u32 usart, u32 flag)
+{
+ return ((USART_SR(usart) & flag) != 0);
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief USART Return Interrupt Source.
+
+Returns true if the specified interrupt flag (IDLE, RXNE, TC, TXE or OE) was
+set and the interrupt was enabled. If the specified flag is not an interrupt
+flag, the function returns false.
+
+@todo These are the most important interrupts likely to be used. Others
+relating to LIN break, and error conditions in multibuffer communication, need
+to be added for completeness.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+@param[in] flag Unsigned int32. Status register flag @ref usart_sr_flags.
+@returns boolean: flag and interrupt enable both set.
+*/
+
+bool usart_get_interrupt_source(u32 usart, u32 flag)
+{
+u32 flag_set = (USART_SR(usart) & flag);
+/* IDLE, RXNE, TC, TXE interrupts */
+ if ((flag >= USART_SR_IDLE) && (flag <= USART_SR_TXE))
+ return ((flag_set & USART_CR1(usart)) != 0);
+/* Overrun error */
+ else if (flag == USART_SR_ORE)
+ return (flag_set && (USART_CR3(usart) & USART_CR3_CTSIE));
+ return (false);
+}
+
+/**@}*/
+