diff options
-rw-r--r-- | libmaple/include/libmaple/usart.h | 229 | ||||
-rw-r--r-- | libmaple/rules.mk | 2 | ||||
-rw-r--r-- | libmaple/stm32f1/include/series/usart.h | 76 | ||||
-rw-r--r-- | libmaple/stm32f1/rules.mk | 1 | ||||
-rw-r--r-- | libmaple/stm32f1/usart.c | 170 | ||||
-rw-r--r-- | libmaple/stm32f2/include/series/usart.h | 103 | ||||
-rw-r--r-- | libmaple/stm32f2/rules.mk | 1 | ||||
-rw-r--r-- | libmaple/stm32f2/usart.c | 198 | ||||
-rw-r--r-- | libmaple/usart.c | 138 | ||||
-rw-r--r-- | libmaple/usart_private.c | 40 | ||||
-rw-r--r-- | libmaple/usart_private.h | 53 |
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 |