aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarti Bolivar <mbolivar@leaflabs.com>2012-03-26 15:42:25 -0400
committerMarti Bolivar <mbolivar@leaflabs.com>2012-04-11 16:56:55 -0400
commiteee763308a497105a1aa1aefd3c4b3124e8362b3 (patch)
treedb2381ab15276a26e009e12f8ffb44c38b95229c
parent45763badb4ff7cee56a38b72d7546eae4205630b (diff)
downloadlibrambutan-eee763308a497105a1aa1aefd3c4b3124e8362b3.tar.gz
librambutan-eee763308a497105a1aa1aefd3c4b3124e8362b3.zip
[FIXME] Resurrected, shinier USART support.
FIXME: - Test F1 support - Solve problem of duplicated bytes being TXed unless delay is inserted after configuration but before first bytes are TXed. Rip out nonportable bits from top-level interfaces. The USART register maps are basically the same between F1 and F2, so leave these, but add register bit definitions which had name changes to the libmaple header to avoid needless repetition. There are also a few new bits in the F2 USART registers; add definitions for these in the F2 USART header. Add Doxygen comments for all USART bit definitions. Deprecate struct usart_dev's max_baud field. This is just bloat that doesn't bring us much real benefit. Add new series-specific USART files for F1 and F2: - libmaple/stm32f[1,2]/usart.c - libmaple/stm32f[1,2]/include/series/usart.h These are standard series-specific files, providing register map base pointers, defining devices, implementing nonportable routines, etc. We need a portable way to configure the USART GPIOs. To this end, add usart_async_gpio_cfg() to the top-level USART interface. This function is implemented in new F1 and F2 USART backends to take the appropriate action to configure the RX and TX pins for asynchronous full duplex mode. USART baud rate calculation is done differently on the different series. Keep the usart_set_baud_rate() declaration in the top-level USART header, but move the implementations into the series-specific usart.c files. In usart_set_baud_rate(), allow for deriving clock_speed automatically by letting user tell us to figure out the peripheral clock speed by mapping the device's rcc_clk_id onto an STM32_PCLK[1,2] value. This preserves flexibility for users with non-default clock configurations, but makes things easier on everyone else. Add private USART files for portable private USART routines: - libmaple/usart_private.h - libmaple/usart_private.c Signed-off-by: Marti Bolivar <mbolivar@leaflabs.com>
-rw-r--r--libmaple/include/libmaple/usart.h229
-rw-r--r--libmaple/rules.mk2
-rw-r--r--libmaple/stm32f1/include/series/usart.h76
-rw-r--r--libmaple/stm32f1/rules.mk1
-rw-r--r--libmaple/stm32f1/usart.c170
-rw-r--r--libmaple/stm32f2/include/series/usart.h103
-rw-r--r--libmaple/stm32f2/rules.mk1
-rw-r--r--libmaple/stm32f2/usart.c198
-rw-r--r--libmaple/usart.c138
-rw-r--r--libmaple/usart_private.c40
-rw-r--r--libmaple/usart_private.h53
11 files changed, 836 insertions, 175 deletions
diff --git a/libmaple/include/libmaple/usart.h b/libmaple/include/libmaple/usart.h
index f9bdb8b..42f9576 100644
--- a/libmaple/include/libmaple/usart.h
+++ b/libmaple/include/libmaple/usart.h
@@ -43,9 +43,10 @@ extern "C"{
#include <libmaple/rcc.h>
#include <libmaple/nvic.h>
#include <libmaple/ring_buffer.h>
+#include <series/usart.h>
/*
- * Register maps and devices
+ * Register map (common across supported STM32 series).
*/
/** USART register map type */
@@ -59,169 +60,315 @@ typedef struct usart_reg_map {
__io uint32 GTPR; /**< Guard time and prescaler register */
} usart_reg_map;
-/** USART1 register map base pointer */
-#define USART1_BASE ((struct usart_reg_map*)0x40013800)
-/** USART2 register map base pointer */
-#define USART2_BASE ((struct usart_reg_map*)0x40004400)
-/** USART3 register map base pointer */
-#define USART3_BASE ((struct usart_reg_map*)0x40004800)
-#ifdef STM32_HIGH_DENSITY
-/** UART4 register map base pointer */
-#define UART4_BASE ((struct usart_reg_map*)0x40004C00)
-/** UART5 register map base pointer */
-#define UART5_BASE ((struct usart_reg_map*)0x40005000)
-#endif
-
/*
* Register bit definitions
*/
/* Status register */
+/** Clear to send bit */
#define USART_SR_CTS_BIT 9
+/** Line break detection bit */
#define USART_SR_LBD_BIT 8
+/** Transmit data register empty bit */
#define USART_SR_TXE_BIT 7
+/** Transmission complete bit */
#define USART_SR_TC_BIT 6
+/** Read data register not empty bit */
#define USART_SR_RXNE_BIT 5
+/** IDLE line detected bit */
#define USART_SR_IDLE_BIT 4
+/** Overrun error bit */
#define USART_SR_ORE_BIT 3
+/** Noise error bit */
#define USART_SR_NE_BIT 2
+/**
+ * @brief Synonym for USART_SR_NE_BIT.
+ *
+ * Some series (e.g. STM32F2) use "NF" for "noise flag" instead of the
+ * original "NE" for "noise error". The meaning of the bit is
+ * unchanged, but the NF flag can be disabled when the line is
+ * noise-free.
+ *
+ * @see USART_SR_NE_BIT
+ */
+#define USART_SR_NF_BIT USART_SR_NE_BIT
+/** Framing error bit */
#define USART_SR_FE_BIT 1
+/** Parity error bit */
#define USART_SR_PE_BIT 0
+/** Clear to send mask */
#define USART_SR_CTS BIT(USART_SR_CTS_BIT)
+/** Line break detected mask */
#define USART_SR_LBD BIT(USART_SR_LBD_BIT)
+/** Transmit data register empty mask */
#define USART_SR_TXE BIT(USART_SR_TXE_BIT)
+/** Transmission complete mask */
#define USART_SR_TC BIT(USART_SR_TC_BIT)
+/** Read data register not empty mask */
#define USART_SR_RXNE BIT(USART_SR_RXNE_BIT)
+/** IDLE line detected mask */
#define USART_SR_IDLE BIT(USART_SR_IDLE_BIT)
+/** Overrun error mask */
#define USART_SR_ORE BIT(USART_SR_ORE_BIT)
+/** Noise error mask */
#define USART_SR_NE BIT(USART_SR_NE_BIT)
+/**
+ * @brief Synonym for USART_SR_NE.
+ * @see USART_SR_NF_BIT
+ */
+#define USART_SR_NF USART_SR_NE
+/** Framing error mask */
#define USART_SR_FE BIT(USART_SR_FE_BIT)
+/** Parity error mask */
#define USART_SR_PE BIT(USART_SR_PE_BIT)
/* Data register */
+/** Data register data value mask */
#define USART_DR_DR 0xFF
/* Baud rate register */
+/** Mantissa of USARTDIV mask */
#define USART_BRR_DIV_MANTISSA (0xFFF << 4)
+/** Fraction of USARTDIV mask */
#define USART_BRR_DIV_FRACTION 0xF
/* Control register 1 */
+/** USART enable bit */
#define USART_CR1_UE_BIT 13
+/** Word length bit */
#define USART_CR1_M_BIT 12
+/** Wakeup method bit */
#define USART_CR1_WAKE_BIT 11
+/** Parity control enable bit */
#define USART_CR1_PCE_BIT 10
+/** Parity selection bit */
#define USART_CR1_PS_BIT 9
+/** Parity error interrupt enable bit */
#define USART_CR1_PEIE_BIT 8
+/** Transmit data regsiter not empty interrupt enable bit */
#define USART_CR1_TXEIE_BIT 7
+/** Transmission complete interrupt enable bit */
#define USART_CR1_TCIE_BIT 6
+/** RXNE interrupt enable bit */
#define USART_CR1_RXNEIE_BIT 5
+/** IDLE interrupt enable bit */
#define USART_CR1_IDLEIE_BIT 4
+/** Transmitter enable bit */
#define USART_CR1_TE_BIT 3
+/** Receiver enable bit */
#define USART_CR1_RE_BIT 2
+/** Receiver wakeup bit */
#define USART_CR1_RWU_BIT 1
+/** Send break bit */
#define USART_CR1_SBK_BIT 0
+/** USART enable mask */
#define USART_CR1_UE BIT(USART_CR1_UE_BIT)
+/** Word length mask */
#define USART_CR1_M BIT(USART_CR1_M_BIT)
+/** Word length: 1 start bit, 8 data bits, n stop bit */
+#define USART_CR1_M_8N1 (0 << USART_CR1_M_BIT)
+/** Word length: 1 start bit, 9 data bits, n stop bit */
+#define USART_CR1_M_9N1 (1 << USART_CR1_M_BIT)
+/** Wakeup method mask */
#define USART_CR1_WAKE BIT(USART_CR1_WAKE_BIT)
+/** Wakeup on idle line */
#define USART_CR1_WAKE_IDLE (0 << USART_CR1_WAKE_BIT)
+/** Wakeup on address mark */
#define USART_CR1_WAKE_ADDR (1 << USART_CR1_WAKE_BIT)
+/** Parity control enable mask */
#define USART_CR1_PCE BIT(USART_CR1_PCE_BIT)
+/** Parity selection mask */
#define USART_CR1_PS BIT(USART_CR1_PS_BIT)
+/** Parity selection: even parity */
#define USART_CR1_PS_EVEN (0 << USART_CR1_PS_BIT)
+/** Parity selection: odd parity */
#define USART_CR1_PS_ODD (1 << USART_CR1_PS_BIT)
+/** Parity error interrupt enable mask */
#define USART_CR1_PEIE BIT(USART_CR1_PEIE_BIT)
+/** Transmit data register empty interrupt enable mask */
#define USART_CR1_TXEIE BIT(USART_CR1_TXEIE_BIT)
+/** Transmission complete interrupt enable mask */
#define USART_CR1_TCIE BIT(USART_CR1_TCIE_BIT)
+/** RXNE interrupt enable mask */
#define USART_CR1_RXNEIE BIT(USART_CR1_RXNEIE_BIT)
+/** IDLE line interrupt enable mask */
#define USART_CR1_IDLEIE BIT(USART_CR1_IDLEIE_BIT)
+/** Transmitter enable mask */
#define USART_CR1_TE BIT(USART_CR1_TE_BIT)
+/** Receiver enable mask */
#define USART_CR1_RE BIT(USART_CR1_RE_BIT)
+/** Receiver wakeup mask */
#define USART_CR1_RWU BIT(USART_CR1_RWU_BIT)
+/** Receiver wakeup: receiver in active mode */
#define USART_CR1_RWU_ACTIVE (0 << USART_CR1_RWU_BIT)
+/** Receiver wakeup: receiver in mute mode */
#define USART_CR1_RWU_MUTE (1 << USART_CR1_RWU_BIT)
+/** Send break */
#define USART_CR1_SBK BIT(USART_CR1_SBK_BIT)
/* Control register 2 */
+/** LIN mode enable bit */
#define USART_CR2_LINEN_BIT 14
+/** Clock enable bit */
#define USART_CR2_CLKEN_BIT 11
+/** Clock polarity bit */
#define USART_CR2_CPOL_BIT 10
+/** Clock phase bit */
#define USART_CR2_CPHA_BIT 9
+/** Last bit clock pulse bit */
#define USART_CR2_LBCL_BIT 8
+/** LIN break detection interrupt enable bit */
#define USART_CR2_LBDIE_BIT 6
+/** LIN break detection length bit */
#define USART_CR2_LBDL_BIT 5
+/** LIN mode enable mask */
#define USART_CR2_LINEN BIT(USART_CR2_LINEN_BIT)
+/** STOP bits mask */
#define USART_CR2_STOP (0x3 << 12)
+/** STOP bits: 1 stop bit */
#define USART_CR2_STOP_BITS_1 (0x0 << 12)
-/* Not on UART4, UART5 */
+/**
+ * @brief STOP bits: 0.5 stop bits
+ * Not available on UART4, UART5. */
#define USART_CR2_STOP_BITS_POINT_5 (0x1 << 12)
-/* Not on UART4, UART5 */
-#define USART_CR2_STOP_BITS_1_POINT_5 (0x3 << 12)
+/** STOP bits: 2 stop bits */
#define USART_CR2_STOP_BITS_2 (0x2 << 12)
+/**
+ * @brief STOP bits: 1.5 stop bits
+ * Not available on UART4, UART5. */
+#define USART_CR2_STOP_BITS_1_POINT_5 (0x3 << 12)
+/**
+ * @brief Clock enable.
+ * Not available on UART4, UART5 */
#define USART_CR2_CLKEN BIT(USART_CR2_CLKEN_BIT)
-/* Not on UART4, UART5 */
+/**
+ * @brief Clock polarity mask.
+ * Not available on UART4, UART5 */
#define USART_CR2_CPOL BIT(USART_CR2_CPOL_BIT)
+/** Clock polarity: low */
#define USART_CR2_CPOL_LOW (0x0 << USART_CR2_CLKEN_BIT)
+/** Clock polarity: high */
#define USART_CR2_CPOL_HIGH (0x1 << USART_CR2_CLKEN_BIT)
-/* Not on UART4, UART5 */
+/**
+ * @brief Clock phase mask.
+ * Not available on UART4, UART5 */
#define USART_CR2_CPHA BIT(USART_CR2_CPHA_BIT)
+/**
+ * @brief Clock phase: first
+ * First clock transition is the first data capture edge. */
#define USART_CR2_CPHA_FIRST (0x0 << USART_CR2_CPHA_BIT)
+/**
+ * @brief Clock phase: second
+ * Second clock transition is the first data capture edge. */
#define USART_CR2_CPHA_SECOND (0x1 << USART_CR2_CPHA_BIT)
-/* Not on UART4, UART5 */
+/**
+ * @brief Last bit clock pulse mask.
+ *
+ * When set, the last bit transmitted causes a clock pulse in
+ * synchronous mode.
+ *
+ * Not available on UART4, UART5 */
#define USART_CR2_LBCL BIT(USART_CR2_LBCL_BIT)
+/** LIN break detection interrupt enable mask. */
#define USART_CR2_LBDIE BIT(USART_CR2_LBDIE_BIT)
+/** LIN break detection length. */
#define USART_CR2_LBDL BIT(USART_CR2_LBDL_BIT)
+/** LIN break detection length: 10 bits */
#define USART_CR2_LBDL_10_BIT (0 << USART_CR2_LBDL_BIT)
+/** LIN break detection length: 11 bits */
#define USART_CR2_LBDL_11_BIT (1 << USART_CR2_LBDL_BIT)
+/**
+ * @brief Address of the USART node
+ * This is useful during multiprocessor communication. */
#define USART_CR2_ADD 0xF
/* Control register 3 */
+/** Clear to send interrupt enable bit */
#define USART_CR3_CTSIE_BIT 10
+/** Clear to send enable bit */
#define USART_CR3_CTSE_BIT 9
+/** Ready to send enable bit */
#define USART_CR3_RTSE_BIT 8
+/** DMA enable transmitter bit */
#define USART_CR3_DMAT_BIT 7
+/** DMA enable receiver bit */
#define USART_CR3_DMAR_BIT 6
+/** Smartcard mode enable bit */
#define USART_CR3_SCEN_BIT 5
+/** Smartcard NACK enable bit */
#define USART_CR3_NACK_BIT 4
+/** Half-duplex selection bit */
#define USART_CR3_HDSEL_BIT 3
+/** IrDA low power bit */
#define USART_CR3_IRLP_BIT 2
+/** IrDA mode enable bit */
#define USART_CR3_IREN_BIT 1
+/** Error interrupt enable bit */
#define USART_CR3_EIE_BIT 0
-/* Not on UART4, UART5 */
+/**
+ * @brief Clear to send interrupt enable
+ * Not available on UART4, UART5. */
#define USART_CR3_CTSIE BIT(USART_CR3_CTSIE_BIT)
-/* Not on UART4, UART5 */
+/**
+ * @brief Clear to send enable
+ * Not available on UART4, UART5. */
#define USART_CR3_CTSE BIT(USART_CR3_CTSE_BIT)
-/* Not on UART4, UART5 */
+/**
+ * @brief Ready to send enable
+ * Not available on UART4, UART5. */
#define USART_CR3_RTSE BIT(USART_CR3_RTSE_BIT)
-/* Not on UART5 */
+/**
+ * @brief DMA enable transmitter
+ * Not available on UART5. */
#define USART_CR3_DMAT BIT(USART_CR3_DMAT_BIT)
-/* Not on UART5 */
+/**
+ * @brief DMA enable receiver
+ * Not available on UART5. */
#define USART_CR3_DMAR BIT(USART_CR3_DMAR_BIT)
-/* Not on UART4, UART5 */
+/**
+ * @brief Smartcard mode enable
+ * Not available on UART4, UART5. */
#define USART_CR3_SCEN BIT(USART_CR3_SCEN_BIT)
-/* Not on UART4, UART5 */
+/**
+ * @brief Smartcard NACK enable
+ * Not available on UART4, UART5. */
#define USART_CR3_NACK BIT(USART_CR3_NACK_BIT)
+/**
+ * @brief Half-duplex selection
+ * When set, single-wire half duplex mode is selected.
+ */
#define USART_CR3_HDSEL BIT(USART_CR3_HDSEL_BIT)
+/** IrDA low power mode */
#define USART_CR3_IRLP BIT(USART_CR3_IRLP_BIT)
-#define USART_CR3_IRLP_NORMAL (0 << USART_CR3_IRLP_BIT)
-#define USART_CR3_IRLP_LOW_POWER (1 << USART_CR3_IRLP_BIT)
+/** IrDA mode: normal */
+#define USART_CR3_IRLP_NORMAL (0U << USART_CR3_IRLP_BIT)
+/** IrDA mode: low power */
+#define USART_CR3_IRLP_LOW_POWER (1U << USART_CR3_IRLP_BIT)
+/** IrDA mode enable */
#define USART_CR3_IREN BIT(USART_CR3_IREN_BIT)
+/** Error interrupt enable */
#define USART_CR3_EIE BIT(USART_CR3_EIE_BIT)
/* Guard time and prescaler register */
-/* Not on UART4, UART5 */
+/**
+ * @brief Guard time value mask
+ * Used in Smartcard mode. Not available on UART4, UART5. */
#define USART_GTPR_GT (0xFF << 8)
-/* Not on UART4, UART5 */
+/**
+ * @brief Prescaler value mask
+ * Restrictions on this value apply, depending on the USART mode. Not
+ * available on UART4, UART5. */
#define USART_GTPR_PSC 0xFF
/*
@@ -236,7 +383,8 @@ typedef struct usart_reg_map {
typedef struct usart_dev {
usart_reg_map *regs; /**< Register map */
ring_buffer *rb; /**< RX ring buffer */
- uint32 max_baud; /**< Maximum baud */
+ uint32 max_baud; /**< @brief Deprecated.
+ * Maximum baud rate. */
uint8 rx_buf[USART_RX_BUF_SIZE]; /**< @brief Deprecated.
* Actual RX buffer used by rb.
* This field will be removed in
@@ -245,16 +393,17 @@ typedef struct usart_dev {
nvic_irq_num irq_num; /**< USART NVIC interrupt */
} usart_dev;
-extern usart_dev *USART1;
-extern usart_dev *USART2;
-extern usart_dev *USART3;
-#ifdef STM32_HIGH_DENSITY
-extern usart_dev *UART4;
-extern usart_dev *UART5;
-#endif
-
void usart_init(usart_dev *dev);
+
+struct gpio_dev; /* forward declaration */
+void usart_async_gpio_cfg(usart_dev *udev,
+ struct gpio_dev *rx_dev, uint8 rx,
+ struct gpio_dev *tx_dev, uint8 tx,
+ unsigned flags);
+
+#define USART_USE_PCLK 0
void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud);
+
void usart_enable(usart_dev *dev);
void usart_disable(usart_dev *dev);
void usart_foreach(void (*fn)(usart_dev *dev));
diff --git a/libmaple/rules.mk b/libmaple/rules.mk
index abb6ab2..5675c1c 100644
--- a/libmaple/rules.mk
+++ b/libmaple/rules.mk
@@ -18,6 +18,8 @@ cSRCS_$(d) += rcc.c
cSRCS_$(d) += syscalls.c
cSRCS_$(d) += systick.c
cSRCS_$(d) += util.c
+cSRCS_$(d) += usart.c
+cSRCS_$(d) += usart_private.c
sSRCS_$(d) := exc.S
diff --git a/libmaple/stm32f1/include/series/usart.h b/libmaple/stm32f1/include/series/usart.h
new file mode 100644
index 0000000..93a7728
--- /dev/null
+++ b/libmaple/stm32f1/include/series/usart.h
@@ -0,0 +1,76 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2012 LeafLabs, LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *****************************************************************************/
+
+/**
+ * @file libmaple/stm32f1/usart.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F1 USART header.
+ */
+
+#ifndef _LIBMAPLE_STM32F1_USART_H_
+#define _LIBMAPLE_STM32F1_USART_H_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/*
+ * Register map base pointers
+ */
+
+struct usart_reg_map;
+
+/** USART1 register map base pointer */
+#define USART1_BASE ((struct usart_reg_map*)0x40013800)
+/** USART2 register map base pointer */
+#define USART2_BASE ((struct usart_reg_map*)0x40004400)
+/** USART3 register map base pointer */
+#define USART3_BASE ((struct usart_reg_map*)0x40004800)
+#ifdef STM32_HIGH_DENSITY
+/** UART4 register map base pointer */
+#define UART4_BASE ((struct usart_reg_map*)0x40004C00)
+/** UART5 register map base pointer */
+#define UART5_BASE ((struct usart_reg_map*)0x40005000)
+#endif
+
+/*
+ * Devices
+ */
+
+struct usart_dev;
+extern struct usart_dev *USART1;
+extern struct usart_dev *USART2;
+extern struct usart_dev *USART3;
+#ifdef STM32_HIGH_DENSITY
+extern struct usart_dev *UART4;
+extern struct usart_dev *UART5;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk
index 4c7db60..3d34797 100644
--- a/libmaple/stm32f1/rules.mk
+++ b/libmaple/stm32f1/rules.mk
@@ -14,6 +14,7 @@ sSRCS_$(d) := isrs_performance.S \
cSRCS_$(d) := rcc.c
cSRCS_$(d) += gpio.c
cSRCS_$(d) += bkp.c
+cSRCS_$(d) += usart.c
sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%)
cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%)
diff --git a/libmaple/stm32f1/usart.c b/libmaple/stm32f1/usart.c
new file mode 100644
index 0000000..ee68082
--- /dev/null
+++ b/libmaple/stm32f1/usart.c
@@ -0,0 +1,170 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2012 LeafLabs, LLC.
+ * Copyright (c) 2010 Perry Hung.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *****************************************************************************/
+
+/**
+ * @file libmaple/stm32f1/usart.c
+ * @author Marti Bolivar <mbolivar@leaflabs.com>,
+ * Perry Hung <perry@leaflabs.com>
+ * @brief STM32F1 USART support.
+ */
+
+#include <libmaple/usart.h>
+#include <libmaple/gpio.h>
+#include "usart_private.h"
+
+/*
+ * Devices
+ */
+
+static ring_buffer usart1_rb;
+static usart_dev usart1 = {
+ .regs = USART1_BASE,
+ .rb = &usart1_rb,
+ .max_baud = 4500000UL,
+ .clk_id = RCC_USART1,
+ .irq_num = NVIC_USART1,
+};
+/** USART1 device */
+usart_dev *USART1 = &usart1;
+
+static ring_buffer usart2_rb;
+static usart_dev usart2 = {
+ .regs = USART2_BASE,
+ .rb = &usart2_rb,
+ .max_baud = 2250000UL,
+ .clk_id = RCC_USART2,
+ .irq_num = NVIC_USART2,
+};
+/** USART2 device */
+usart_dev *USART2 = &usart2;
+
+static ring_buffer usart3_rb;
+static usart_dev usart3 = {
+ .regs = USART3_BASE,
+ .rb = &usart3_rb,
+ .max_baud = 2250000UL,
+ .clk_id = RCC_USART3,
+ .irq_num = NVIC_USART3,
+};
+/** USART3 device */
+usart_dev *USART3 = &usart3;
+
+#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
+static ring_buffer uart4_rb;
+static usart_dev uart4 = {
+ .regs = UART4_BASE,
+ .rb = &uart4_rb,
+ .max_baud = 2250000UL,
+ .clk_id = RCC_UART4,
+ .irq_num = NVIC_UART4,
+};
+/** UART4 device */
+usart_dev *UART4 = &uart4;
+
+static ring_buffer uart5_rb;
+static usart_dev uart5 = {
+ .regs = UART5_BASE,
+ .rb = &uart5_rb,
+ .max_baud = 2250000UL,
+ .clk_id = RCC_UART5,
+ .irq_num = NVIC_UART5,
+};
+/** UART5 device */
+usart_dev *UART5 = &uart5;
+#endif
+
+/*
+ * Routines
+ */
+
+void usart_async_gpio_cfg(usart_dev *udev,
+ gpio_dev *rx_dev, uint8 rx,
+ gpio_dev *tx_dev, uint8 tx,
+ unsigned flags) {
+ gpio_set_mode(rx_dev, rx, GPIO_INPUT_FLOATING);
+ gpio_set_mode(tx_dev, tx, GPIO_AF_OUTPUT_PP);
+}
+
+void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud) {
+ uint32 integer_part;
+ uint32 fractional_part;
+ uint32 tmp;
+
+ /* Figure out the clock speed, if the user doesn't give one. */
+ if (clock_speed == 0) {
+ clock_speed = _usart_clock_freq(dev);
+ }
+ ASSERT(clock_speed);
+
+ /* Convert desired baud rate to baud rate register setting. */
+ integer_part = (25 * clock_speed) / (4 * baud);
+ tmp = (integer_part / 100) << 4;
+ fractional_part = integer_part - (100 * (tmp >> 4));
+ tmp |= (((fractional_part * 16) + 50) / 100) & ((uint8)0x0F);
+
+ dev->regs->BRR = (uint16)tmp;
+}
+
+/**
+ * @brief Call a function on each USART.
+ * @param fn Function to call.
+ */
+void usart_foreach(void (*fn)(usart_dev*)) {
+ fn(USART1);
+ fn(USART2);
+ fn(USART3);
+#ifdef STM32_HIGH_DENSITY
+ fn(UART4);
+ fn(UART5);
+#endif
+}
+
+/*
+ * Interrupt handlers.
+ */
+
+void __irq_usart1(void) {
+ usart_irq(&usart1_rb, USART1_BASE);
+}
+
+void __irq_usart2(void) {
+ usart_irq(&usart2_rb, USART2_BASE);
+}
+
+void __irq_usart3(void) {
+ usart_irq(&usart3_rb, USART3_BASE);
+}
+
+#ifdef STM32_HIGH_DENSITY
+void __irq_uart4(void) {
+ usart_irq(&uart4_rb, UART4_BASE);
+}
+
+void __irq_uart5(void) {
+ usart_irq(&uart5_rb, UART5_BASE);
+}
+#endif
diff --git a/libmaple/stm32f2/include/series/usart.h b/libmaple/stm32f2/include/series/usart.h
new file mode 100644
index 0000000..9b18b9c
--- /dev/null
+++ b/libmaple/stm32f2/include/series/usart.h
@@ -0,0 +1,103 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2012 LeafLabs, LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *****************************************************************************/
+
+/**
+ * @file libmaple/stm32f2/usart.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F2 USART header.
+ */
+
+#ifndef _LIBMAPLE_STM32F2_USART_H_
+#define _LIBMAPLE_STM32F2_USART_H_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/*
+ * Register map base pointers.
+ */
+
+struct usart_reg_map;
+
+/** USART1 register map base pointer */
+#define USART1_BASE ((struct usart_reg_map*)0x40011000)
+/** USART2 register map base pointer */
+#define USART2_BASE ((struct usart_reg_map*)0x40004400)
+/** USART3 register map base pointer */
+#define USART3_BASE ((struct usart_reg_map*)0x40004800)
+/** UART4 register map base pointer */
+#define UART4_BASE ((struct usart_reg_map*)0x40004C00)
+/** UART5 register map base pointer */
+#define UART5_BASE ((struct usart_reg_map*)0x40005000)
+/** USART6 register map base pointer */
+#define USART6_BASE ((struct usart_reg_map*)0x40011400)
+
+/*
+ * F2-only register bit definitions.
+ */
+
+/* Control register 1 */
+
+/**
+ * @brief Oversampling mode bit.
+ * Availability: STM32F2. */
+#define USART_CR1_OVER8_BIT 15
+
+/**
+ * @brief Oversampling mode.
+ * Availability: STM32F2. */
+#define USART_CR1_OVER8 (1U << USART_CR1_OVER8_BIT)
+
+/* Control register 3 */
+
+/** One sample bit method enable bit. */
+#define USART_CR3_ONEBIT_BIT 11
+
+/** One bit sample method enable. */
+#define USART_CR3_ONEBIT (1 << USART_CR3_ONEBIT_BIT)
+/** Sample method: Three sample bit method. */
+#define USART_CR3_ONEBIT_3SAMPLE (0 << USART_CR3_ONEBIT_BIT)
+/** Sample method: One sample bit method. */
+#define USART_CR3_ONEBIT_1SAMPLE (1 << USART_CR3_ONEBIT_BIT)
+
+/*
+ * Devices
+ */
+
+struct usart_dev;
+extern struct usart_dev *USART1;
+extern struct usart_dev *USART2;
+extern struct usart_dev *USART3;
+extern struct usart_dev *UART4;
+extern struct usart_dev *UART5;
+extern struct usart_dev *USART6;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmaple/stm32f2/rules.mk b/libmaple/stm32f2/rules.mk
index 83ab043..54fa068 100644
--- a/libmaple/stm32f2/rules.mk
+++ b/libmaple/stm32f2/rules.mk
@@ -11,6 +11,7 @@ CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) $(LIBMAPLE_PRIVATE_INCLUDES) -Wall -We
sSRCS_$(d) := isrs.S vector_table.S
cSRCS_$(d) := rcc.c
cSRCS_$(d) += gpio.c
+cSRCS_$(d) += usart.c
sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%)
cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%)
diff --git a/libmaple/stm32f2/usart.c b/libmaple/stm32f2/usart.c
new file mode 100644
index 0000000..364558c
--- /dev/null
+++ b/libmaple/stm32f2/usart.c
@@ -0,0 +1,198 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2012 LeafLabs, LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *****************************************************************************/
+
+/**
+ * @file libmaple/stm32f2/usart.c
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F2 USART support.
+ */
+
+#include <libmaple/usart.h>
+#include <libmaple/gpio.h>
+#include "usart_private.h"
+
+/*
+ * Devices
+ */
+
+static ring_buffer usart1_rb;
+static usart_dev usart1 = {
+ .regs = USART1_BASE,
+ .rb = &usart1_rb,
+ .max_baud = 4500000UL, /* FIXME */
+ .clk_id = RCC_USART1,
+ .irq_num = NVIC_USART1,
+};
+/** USART1 device */
+usart_dev *USART1 = &usart1;
+
+static ring_buffer usart2_rb;
+static usart_dev usart2 = {
+ .regs = USART2_BASE,
+ .rb = &usart2_rb,
+ .max_baud = 2250000UL, /* FIXME */
+ .clk_id = RCC_USART2,
+ .irq_num = NVIC_USART2,
+};
+/** USART2 device */
+usart_dev *USART2 = &usart2;
+
+static ring_buffer usart3_rb;
+static usart_dev usart3 = {
+ .regs = USART3_BASE,
+ .rb = &usart3_rb,
+ .max_baud = 2250000UL, /* FIXME */
+ .clk_id = RCC_USART3,
+ .irq_num = NVIC_USART3,
+};
+/** USART3 device */
+usart_dev *USART3 = &usart3;
+
+static ring_buffer uart4_rb;
+static usart_dev uart4 = {
+ .regs = UART4_BASE,
+ .rb = &uart4_rb,
+ .max_baud = 2250000UL, /* FIXME */
+ .clk_id = RCC_UART4,
+ .irq_num = NVIC_UART4,
+};
+/** UART4 device */
+usart_dev *UART4 = &uart4;
+
+static ring_buffer uart5_rb;
+static usart_dev uart5 = {
+ .regs = UART5_BASE,
+ .rb = &uart5_rb,
+ .max_baud = 2250000UL, /* FIXME */
+ .clk_id = RCC_UART5,
+ .irq_num = NVIC_UART5,
+};
+/** UART5 device */
+usart_dev *UART5 = &uart5;
+
+static ring_buffer usart6_rb;
+static usart_dev usart6 = {
+ .regs = USART6_BASE,
+ .rb = &usart6_rb,
+ .max_baud = 4500000UL, /* FIXME */
+ .clk_id = RCC_USART6,
+ .irq_num = NVIC_USART6,
+};
+usart_dev *USART6 = &usart6;
+
+/*
+ * Routines
+ */
+
+void usart_async_gpio_cfg(usart_dev *udev,
+ gpio_dev *rx_dev, uint8 rx,
+ gpio_dev *tx_dev, uint8 tx,
+ unsigned flags) {
+ gpio_af af;
+ switch (udev->clk_id) {
+ case RCC_USART1:
+ case RCC_USART2:
+ case RCC_USART3:
+ af = GPIO_AF_USART_1_2_3;
+ break;
+ case RCC_UART4:
+ case RCC_UART5:
+ case RCC_USART6:
+ af = GPIO_AF_USART_4_5_6;
+ break;
+ default:
+ ASSERT(0);
+ return;
+ }
+ gpio_set_modef(rx_dev, rx, GPIO_MODE_AF, 0);
+ gpio_set_modef(tx_dev, tx, GPIO_MODE_AF, 0);
+ gpio_set_af(rx_dev, rx, af);
+ gpio_set_af(tx_dev, tx, af);
+}
+
+void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud) {
+ uint32 integer_part;
+ uint32 fractional_part;
+ uint32 tmp;
+ uint32 over8 = !!(dev->regs->CR1 & USART_CR1_OVER8);
+
+ ASSERT(!over8); /* OVER8 is currently unsupported. */
+
+ /* Figure out the clock speed, if the user doesn't give one. */
+ if (clock_speed == 0) {
+ clock_speed = _usart_clock_freq(dev);
+ }
+ ASSERT(clock_speed);
+
+ /* Convert desired baud rate to baud rate register setting. */
+ integer_part = (25 * clock_speed) / (2 * (2 - over8) * baud);
+ tmp = (integer_part / 100) << 4;
+ fractional_part = integer_part - (100 * (tmp >> 4));
+ tmp |= ((fractional_part * 16 + 50) / 100) & (uint8)0x0F;
+
+ dev->regs->BRR = tmp;
+}
+
+/**
+ * @brief Call a function on each USART.
+ * @param fn Function to call.
+ */
+void usart_foreach(void (*fn)(usart_dev*)) {
+ fn(USART1);
+ fn(USART2);
+ fn(USART3);
+ fn(UART4);
+ fn(UART5);
+ fn(USART6);
+}
+
+/*
+ * Interrupt handlers.
+ */
+
+void __irq_usart1(void) {
+ usart_irq(&usart1_rb, USART1_BASE);
+}
+
+void __irq_usart2(void) {
+ usart_irq(&usart2_rb, USART2_BASE);
+}
+
+void __irq_usart3(void) {
+ usart_irq(&usart3_rb, USART3_BASE);
+}
+
+void __irq_uart4(void) {
+ usart_irq(&uart4_rb, UART4_BASE);
+}
+
+void __irq_uart5(void) {
+ usart_irq(&uart5_rb, UART5_BASE);
+}
+
+void __irq_usart6(void) {
+ usart_irq(&usart6_rb, USART6_BASE);
+}
diff --git a/libmaple/usart.c b/libmaple/usart.c
index ba63b79..1070aa2 100644
--- a/libmaple/usart.c
+++ b/libmaple/usart.c
@@ -33,67 +33,6 @@
#include <libmaple/usart.h>
-/*
- * Devices
- */
-
-static ring_buffer usart1_rb;
-static usart_dev usart1 = {
- .regs = USART1_BASE,
- .rb = &usart1_rb,
- .max_baud = 4500000UL,
- .clk_id = RCC_USART1,
- .irq_num = NVIC_USART1
-};
-/** USART1 device */
-usart_dev *USART1 = &usart1;
-
-static ring_buffer usart2_rb;
-static usart_dev usart2 = {
- .regs = USART2_BASE,
- .rb = &usart2_rb,
- .max_baud = 2250000UL,
- .clk_id = RCC_USART2,
- .irq_num = NVIC_USART2
-};
-/** USART2 device */
-usart_dev *USART2 = &usart2;
-
-static ring_buffer usart3_rb;
-static usart_dev usart3 = {
- .regs = USART3_BASE,
- .rb = &usart3_rb,
- .max_baud = 2250000UL,
- .clk_id = RCC_USART3,
- .irq_num = NVIC_USART3
-};
-/** USART3 device */
-usart_dev *USART3 = &usart3;
-
-#ifdef STM32_HIGH_DENSITY
-static ring_buffer uart4_rb;
-static usart_dev uart4 = {
- .regs = UART4_BASE,
- .rb = &uart4_rb,
- .max_baud = 2250000UL,
- .clk_id = RCC_UART4,
- .irq_num = NVIC_UART4
-};
-/** UART4 device */
-usart_dev *UART4 = &uart4;
-
-static ring_buffer uart5_rb;
-static usart_dev uart5 = {
- .regs = UART5_BASE,
- .rb = &uart5_rb,
- .max_baud = 2250000UL,
- .clk_id = RCC_UART5,
- .irq_num = NVIC_UART5
-};
-/** UART5 device */
-usart_dev *UART5 = &uart5;
-#endif
-
/**
* @brief Initialize a serial port.
* @param dev Serial port to be initialized
@@ -105,27 +44,6 @@ void usart_init(usart_dev *dev) {
}
/**
- * @brief Configure a serial port's baud rate.
- *
- * @param dev Serial port to be configured
- * @param clock_speed Clock speed, in megahertz.
- * @param baud Baud rate for transmit/receive.
- */
-void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud) {
- uint32 integer_part;
- uint32 fractional_part;
- uint32 tmp;
-
- /* See ST RM0008 for the details on configuring the baud rate register */
- integer_part = (25 * clock_speed) / (4 * baud);
- tmp = (integer_part / 100) << 4;
- fractional_part = integer_part - (100 * (tmp >> 4));
- tmp |= (((fractional_part * 16) + 50) / 100) & ((uint8)0x0F);
-
- dev->regs->BRR = (uint16)tmp;
-}
-
-/**
* @brief Enable a serial port.
*
* USART is enabled in single buffer transmission mode, multibuffer
@@ -138,7 +56,8 @@ void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud) {
*/
void usart_enable(usart_dev *dev) {
usart_reg_map *regs = dev->regs;
- regs->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE;
+ regs->CR1 = (USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE |
+ USART_CR1_M_8N1);
regs->CR1 |= USART_CR1_UE;
}
@@ -147,7 +66,7 @@ void usart_enable(usart_dev *dev) {
* @param dev Serial port to be disabled
*/
void usart_disable(usart_dev *dev) {
- /* FIXME this misbehaves if you try to use PWM on TX afterwards */
+ /* FIXME this misbehaves (on F1) if you try to use PWM on TX afterwards */
usart_reg_map *regs = dev->regs;
/* TC bit must be high before disabling the USART */
@@ -162,20 +81,6 @@ void usart_disable(usart_dev *dev) {
}
/**
- * @brief Call a function on each USART.
- * @param fn Function to call.
- */
-void usart_foreach(void (*fn)(usart_dev*)) {
- fn(USART1);
- fn(USART2);
- fn(USART3);
-#ifdef STM32_HIGH_DENSITY
- fn(UART4);
- fn(UART5);
-#endif
-}
-
-/**
* @brief Nonblocking USART transmit
* @param dev Serial port to transmit over
* @param buf Buffer to transmit
@@ -230,40 +135,3 @@ void usart_putudec(usart_dev *dev, uint32 val) {
usart_putc(dev, digits[i]);
}
}
-
-/*
- * Interrupt handlers.
- */
-
-static inline void usart_irq(usart_dev *dev) {
-#ifdef USART_SAFE_INSERT
- /* If the buffer is full and the user defines USART_SAFE_INSERT,
- * ignore new bytes. */
- rb_safe_insert(dev->rb, (uint8)dev->regs->DR);
-#else
- /* By default, push bytes around in the ring buffer. */
- rb_push_insert(dev->rb, (uint8)dev->regs->DR);
-#endif
-}
-
-void __irq_usart1(void) {
- usart_irq(USART1);
-}
-
-void __irq_usart2(void) {
- usart_irq(USART2);
-}
-
-void __irq_usart3(void) {
- usart_irq(USART3);
-}
-
-#ifdef STM32_HIGH_DENSITY
-void __irq_uart4(void) {
- usart_irq(UART4);
-}
-
-void __irq_uart5(void) {
- usart_irq(UART5);
-}
-#endif
diff --git a/libmaple/usart_private.c b/libmaple/usart_private.c
new file mode 100644
index 0000000..d79387a
--- /dev/null
+++ b/libmaple/usart_private.c
@@ -0,0 +1,40 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2012 LeafLabs, LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *****************************************************************************/
+
+/**
+ * @file libmaple/usart_private.c
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief Private USART routines.
+ */
+
+#include "usart_private.h"
+#include <libmaple/rcc.h>
+
+uint32 _usart_clock_freq(usart_dev *dev) {
+ rcc_clk_domain domain = rcc_dev_clk(dev->clk_id);
+ return (domain == RCC_APB1 ? STM32_PCLK1 :
+ (domain == RCC_APB2 ? STM32_PCLK2 : 0));
+}
diff --git a/libmaple/usart_private.h b/libmaple/usart_private.h
new file mode 100644
index 0000000..a5cec83
--- /dev/null
+++ b/libmaple/usart_private.h
@@ -0,0 +1,53 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2012 LeafLabs, LLC.
+ * Copyright (c) 2010 Perry Hung.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *****************************************************************************/
+
+/**
+ * @file libmaple/usart_private.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief Private USART header.
+ */
+
+#ifndef _LIBMAPLE_USART_PRIVATE_H_
+#define _LIBMAPLE_USART_PRIVATE_H_
+
+#include <libmaple/ring_buffer.h>
+#include <libmaple/usart.h>
+
+static inline void usart_irq(ring_buffer *rb, usart_reg_map *regs) {
+#ifdef USART_SAFE_INSERT
+ /* If the buffer is full and the user defines USART_SAFE_INSERT,
+ * ignore new bytes. */
+ rb_safe_insert(rb, (uint8)regs->DR);
+#else
+ /* By default, push bytes around in the ring buffer. */
+ rb_push_insert(rb, (uint8)regs->DR);
+#endif
+}
+
+uint32 _usart_clock_freq(usart_dev *dev);
+
+#endif