aboutsummaryrefslogtreecommitdiffstats
path: root/libmaple
diff options
context:
space:
mode:
authorMarti Bolivar <mbolivar@leaflabs.com>2011-04-06 13:57:30 -0400
committerMarti Bolivar <mbolivar@leaflabs.com>2011-04-07 13:18:36 -0400
commit552b8882ef04cb0028ec30a04b5464b1a17bccad (patch)
tree27332e20a6b5cfad0629917eb257fad24a9589a4 /libmaple
parent012d9ba1c2069d4d072685b990cbd01b611bb751 (diff)
downloadlibrambutan-552b8882ef04cb0028ec30a04b5464b1a17bccad.tar.gz
librambutan-552b8882ef04cb0028ec30a04b5464b1a17bccad.zip
USART refactor.
Diffstat (limited to 'libmaple')
-rw-r--r--libmaple/usart.c302
-rw-r--r--libmaple/usart.h315
-rw-r--r--libmaple/util.c53
3 files changed, 435 insertions, 235 deletions
diff --git a/libmaple/usart.c b/libmaple/usart.c
index 494a29f..df5e2c5 100644
--- a/libmaple/usart.c
+++ b/libmaple/usart.c
@@ -23,212 +23,214 @@
*****************************************************************************/
/**
+ * @file usart.c
* @brief USART control routines
*/
-#include "libmaple.h"
-#include "rcc.h"
-#include "nvic.h"
#include "usart.h"
-#define USART1_BASE 0x40013800
-#define USART2_BASE 0x40004400
-#define USART3_BASE 0x40004800
-#define UART4_BASE 0x40004C00 // High-density devices only (Maple Native)
-#define UART5_BASE 0x40005000 // High-density devices only (Maple Native)
-
-#define USART_UE BIT(13)
-#define USART_M BIT(12)
-#define USART_TE BIT(3)
-#define USART_RE BIT(2)
-#define USART_RXNEIE BIT(5) // read data register not empty interrupt enable
-#define USART_TC BIT(6)
-
-/* usart descriptor table */
-struct usart_dev usart_dev_table[] = {
- [USART1] = {
- .base = (usart_port*)USART1_BASE,
- .rcc_dev_num = RCC_USART1,
- .nvic_dev_num = NVIC_USART1
- },
- [USART2] = {
- .base = (usart_port*)USART2_BASE,
- .rcc_dev_num = RCC_USART2,
- .nvic_dev_num = NVIC_USART2
- },
- [USART3] = {
- .base = (usart_port*)USART3_BASE,
- .rcc_dev_num = RCC_USART3,
- .nvic_dev_num = NVIC_USART3
- },
-#ifdef STM32_HIGH_DENSITY
- /* TODO test */
- [UART4] = {
- .base = (usart_port*)UART4_BASE,
- .rcc_dev_num = RCC_UART4,
- .nvic_dev_num = NVIC_UART4
- },
- [UART5] = {
- .base = (usart_port*)UART5_BASE,
- .rcc_dev_num = RCC_UART5,
- .nvic_dev_num = NVIC_UART5
- },
-#endif
-};
-
/*
- * Usart interrupt handlers.
+ * Devices
*/
-static inline void usart_irq(int usart_num) {
-#ifdef USART_SAFE_INSERT
- /* Ignore old bytes if the user defines USART_SAFE_INSERT. */
- rb_safe_insert(&(usart_dev_table[usart_num].rb),
- (uint8)((usart_dev_table[usart_num].base)->DR));
-#else
- /* By default, push bytes around in the ring buffer. */
- rb_push_insert(&(usart_dev_table[usart_num].rb),
- (uint8)((usart_dev_table[usart_num].base)->DR));
-#endif
-}
-
-/* TODO: Check the disassembly for the following functions to make
- sure GCC inlined properly. */
-
-void __irq_usart1(void) {
- usart_irq(USART1);
-}
-
-void __irq_usart2(void) {
- usart_irq(USART2);
-}
-
-void __irq_usart3(void) {
- usart_irq(USART3);
-}
+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
+};
+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
+};
+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
+};
+usart_dev *USART3 = &usart3;
#ifdef STM32_HIGH_DENSITY
-void __irq_uart4(void) {
- usart_irq(UART4);
-}
-
-void __irq_uart5(void) {
- usart_irq(UART5);
-}
+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
+};
+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
+};
+usart_dev *UART5 = &uart5;
#endif
/**
- * @brief Enable a USART in single buffer transmission mode, multibuffer
- * receiver mode.
- * @param usart_num USART to be initialized
- * @param baud Baud rate to be set at
+ * @brief Initialize a serial port.
+ * @param dev Serial port to be initialized
*/
-void usart_init(uint8 usart_num, uint32 baud) {
-#ifdef STM32_HIGH_DENSITY
- ASSERT(usart_num <= UART5);
-#else
- ASSERT(usart_num <= USART3);
-#endif
- usart_port *port;
- ring_buffer *ring_buf;
+void usart_init(usart_dev *dev) {
+ rb_init(dev->rb, USART_RX_BUF_SIZE, dev->rx_buf);
+ rcc_clk_enable(dev->clk_id);
+ nvic_irq_enable(dev->irq_num);
+}
- uint32 clk_speed;
+/**
+ * @brief Configure a serial port's baud rate.
+ *
+ * @param dev Serial port to be configured
+ * @param clock_speed MCU 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;
- port = usart_dev_table[usart_num].base;
- rcc_clk_enable(usart_dev_table[usart_num].rcc_dev_num);
- nvic_irq_enable(usart_dev_table[usart_num].nvic_dev_num);
-
- /* usart1 is mad fast */
- clk_speed = (usart_num == USART1) ? 72000000UL : 36000000UL;
-
- /* Initialize rx ring buffer */
- rb_init(&usart_dev_table[usart_num].rb,
- sizeof (usart_dev_table[usart_num].rx_buf),
- usart_dev_table[usart_num].rx_buf);
-
- /* Set baud rate */
- integer_part = ((25 * clk_speed) / (4 * baud));
+ /* 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);
- port->BRR = (uint16)tmp;
-
- port->CR1 = USART_TE | // transmitter enable
- USART_RE | // receiver enable
- USART_RXNEIE; // receive interrupt enable
-
-
- /* Enable the USART and set mode to 8n1 */
- port->CR1 |= USART_UE;
+ dev->regs->BRR = (uint16)tmp;
}
/**
- * @brief Turn off all USARTs.
+ * @brief Enable a serial port.
+ *
+ * USART is enabled in single buffer transmission mode, multibuffer
+ * receiver mode, at the given baud rate, 8n1.
+ *
+ * Serial port must have a baud rate configured to work properly.
+ *
+ * @param dev Serial port to enable.
+ * @see usart_set_baud_rate()
*/
-void usart_disable_all() {
- usart_disable(USART1);
- usart_disable(USART2);
- usart_disable(USART3);
-#ifdef STM32_HIGH_DENSITY
- usart_disable(UART4);
- usart_disable(UART5);
-#endif
+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_UE;
}
/**
- * @brief Turn off a USART.
- * @param USART to be disabled
+ * @brief Turn off a serial port.
+ * @param dev Serial port to be disabled
*/
-void usart_disable(uint8 usart_num) {
- usart_port *port = usart_dev_table[usart_num].base;
+void usart_disable(usart_dev *dev) {
+ /* FIXME this misbehaves if you try to use PWM on TX afterwards */
+ usart_reg_map *regs = dev->regs;
- /* TC bit must be high before disabling the usart */
- while((port->CR1 & USART_UE) && !(port->SR & USART_TC))
+ /* TC bit must be high before disabling the USART */
+ while((regs->CR1 & USART_CR1_UE) && !(regs->SR & USART_SR_TC))
;
/* Disable UE */
- port->CR1 = 0;
+ regs->CR1 = 0;
/* Clean up buffer */
- usart_reset_rx(usart_num);
+ usart_reset_rx(dev);
}
+/**
+ * @brief Call a function on each USART.
+ * @param fn Function to call.
+ */
+void usart_foreach(void (*fn)(usart_dev *dev)) {
+ fn(USART1);
+ fn(USART2);
+ fn(USART3);
+#ifdef STM32_HIGH_DENSITY
+ fn(UART4);
+ fn(UART5);
+#endif
+}
/**
- * @brief Print a null terminated string to the specified USART
- *
- * @param usart_num usart to send on
- * @param str string to send
+ * @brief Print a null-terminated string to the specified serial port.
+ * @param dev Serial port to send the string on
+ * @param str String to send
*/
-void usart_putstr(uint8 usart_num, const char* str) {
+void usart_putstr(usart_dev *dev, const char* str) {
char ch;
- while((ch = *(str++)) != '\0') {
- usart_putc(usart_num, ch);
+ while ((ch = *(str++)) != '\0') {
+ usart_putc(dev, ch);
}
}
/**
- * @brief Print an unsigned integer to the specified usart
+ * @brief Print an unsigned integer to the specified serial port.
*
- * @param usart_num usart to send on
- * @param val number to print
+ * @param dev Serial port to send on
+ * @param val Number to print
*/
-void usart_putudec(uint8 usart_num, uint32 val) {
+void usart_putudec(usart_dev *dev, uint32 val) {
char digits[12];
- int i;
+ int i = 0;
- i = 0;
do {
digits[i++] = val % 10 + '0';
val /= 10;
} while (val > 0);
+
while (--i >= 0) {
- usart_putc(usart_num, digits[i]);
+ usart_putc(dev, digits[i]);
}
}
+
+/*
+ * Interrupt handlers.
+ */
+
+static inline void usart_irq(usart_dev *dev) {
+#ifdef USART_SAFE_INSERT
+ /* Ignore new bytes if the user defines USART_SAFE_INSERT. */
+ 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.h b/libmaple/usart.h
index 90b3415..7a93da0 100644
--- a/libmaple/usart.h
+++ b/libmaple/usart.h
@@ -30,94 +30,293 @@
#ifndef _USART_H_
#define _USART_H_
+#include "libmaple_types.h"
+#include "util.h"
+#include "rcc.h"
+#include "nvic.h"
#include "ring_buffer.h"
#ifdef __cplusplus
extern "C"{
#endif
-#define USART_TXE BIT(7)
+/*
+ * Register maps and devices
+ */
+
+/** USART register map type */
+typedef struct usart_reg_map {
+ __io uint32 SR; /**< Status register */
+ __io uint32 DR; /**< Data register */
+ __io uint32 BRR; /**< Baud rate register */
+ __io uint32 CR1; /**< Control register 1 */
+ __io uint32 CR2; /**< Control register 2 */
+ __io uint32 CR3; /**< Control register 3 */
+ __io uint32 GTPR; /**< Guard time and prescaler register */
+} usart_reg_map;
-/* usart device numbers */
-enum {
- USART1,
- USART2,
- USART3,
+/** 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,
- UART5,
+/** 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
-};
-
-/* peripheral register struct */
-typedef struct usart_port {
- volatile uint32 SR; // Status register
- volatile uint32 DR; // Data register
- volatile uint32 BRR; // Baud rate register
- volatile uint32 CR1; // Control register 1
- volatile uint32 CR2; // Control register 2
- volatile uint32 CR3; // Control register 3
- volatile uint32 GTPR; // Guard time and prescaler register
-} usart_port;
-
-/* usart descriptor */
-struct usart_dev {
- usart_port *base;
- ring_buffer rb;
- uint8 rx_buf[64];
- const uint8 rcc_dev_num;
- const uint8 nvic_dev_num;
-};
-
-extern struct usart_dev usart_dev_table[];
+
+/*
+ * Register bit definitions
+ */
+
+/* Status register */
+
+#define USART_SR_CTS_BIT 9
+#define USART_SR_LBD_BIT 8
+#define USART_SR_TXE_BIT 7
+#define USART_SR_TC_BIT 6
+#define USART_SR_RXNE_BIT 5
+#define USART_SR_IDLE_BIT 4
+#define USART_SR_ORE_BIT 3
+#define USART_SR_NE_BIT 2
+#define USART_SR_FE_BIT 1
+#define USART_SR_PE_BIT 0
+
+#define USART_SR_CTS BIT(USART_SR_CTS_BIT)
+#define USART_SR_LBD BIT(USART_SR_LBD_BIT)
+#define USART_SR_TXE BIT(USART_SR_TXE_BIT)
+#define USART_SR_TC BIT(USART_SR_TC_BIT)
+#define USART_SR_RXNE BIT(USART_SR_RXNE_BIT)
+#define USART_SR_IDLE BIT(USART_SR_IDLE_BIT)
+#define USART_SR_ORE BIT(USART_SR_ORE_BIT)
+#define USART_SR_NE BIT(USART_SR_NE_BIT)
+#define USART_SR_FE BIT(USART_SR_FE_BIT)
+#define USART_SR_PE BIT(USART_SR_PE_BIT)
+
+/* Data register */
+
+#define USART_DR_DR 0xFF
+
+/* Baud rate register */
+
+#define USART_BRR_DIV_MANTISSA (0xFFF << 4)
+#define USART_BRR_DIV_FRACTION 0xF
+
+/* Control register 1 */
+
+#define USART_CR1_UE_BIT 13
+#define USART_CR1_M_BIT 12
+#define USART_CR1_WAKE_BIT 11
+#define USART_CR1_PCE_BIT 10
+#define USART_CR1_PS_BIT 9
+#define USART_CR1_PEIE_BIT 8
+#define USART_CR1_TXEIE_BIT 7
+#define USART_CR1_TCIE_BIT 6
+#define USART_CR1_RXNEIE_BIT 5
+#define USART_CR1_IDLEIE_BIT 4
+#define USART_CR1_TE_BIT 3
+#define USART_CR1_RE_BIT 2
+#define USART_CR1_RWU_BIT 1
+#define USART_CR1_SBK_BIT 0
+
+#define USART_CR1_UE BIT(USART_CR1_UE_BIT)
+#define USART_CR1_M BIT(USART_CR1_M_BIT)
+#define USART_CR1_WAKE BIT(USART_CR1_WAKE_BIT)
+#define USART_CR1_WAKE_IDLE (0 << USART_CR1_WAKE_BIT)
+#define USART_CR1_WAKE_ADDR (1 << USART_CR1_WAKE_BIT)
+#define USART_CR1_PCE BIT(USART_CR1_PCE_BIT)
+#define USART_CR1_PS BIT(USART_CR1_PS_BIT)
+#define USART_CR1_PS_EVEN (0 << USART_CR1_PS_BIT)
+#define USART_CR1_PS_ODD (1 << USART_CR1_PS_BIT)
+#define USART_CR1_PEIE BIT(USART_CR1_PEIE_BIT)
+#define USART_CR1_TXEIE BIT(USART_CR1_TXEIE_BIT)
+#define USART_CR1_TCIE BIT(USART_CR1_TCIE_BIT)
+#define USART_CR1_RXNEIE BIT(USART_CR1_RXNEIE_BIT)
+#define USART_CR1_IDLEIE BIT(USART_CR1_IDLEIE_BIT)
+#define USART_CR1_TE BIT(USART_CR1_TE_BIT)
+#define USART_CR1_RE BIT(USART_CR1_RE_BIT)
+#define USART_CR1_RWU BIT(USART_CR1_RWU_BIT)
+#define USART_CR1_RWU_ACTIVE (0 << USART_CR1_RWU_BIT)
+#define USART_CR1_RWU_MUTE (1 << USART_CR1_RWU_BIT)
+#define USART_CR1_SBK BIT(USART_CR1_SBK_BIT)
+
+/* Control register 2 */
+
+#define USART_CR2_LINEN_BIT 14
+#define USART_CR2_CLKEN_BIT 11
+#define USART_CR2_CPOL_BIT 10
+#define USART_CR2_CPHA_BIT 9
+#define USART_CR2_LBCL_BIT 8
+#define USART_CR2_LBDIE_BIT 6
+#define USART_CR2_LBDL_BIT 5
+
+#define USART_CR2_LINEN BIT(USART_CR2_LINEN_BIT)
+#define USART_CR2_STOP (0x3 << 12)
+#define USART_CR2_STOP_BITS_1 (0x0 << 12)
+/* Not 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)
+#define USART_CR2_STOP_BITS_2 (0x2 << 12)
+#define USART_CR2_CLKEN BIT(USART_CR2_CLKEN_BIT)
+/* Not on UART4, UART5 */
+#define USART_CR2_CPOL BIT(USART_CR2_CPOL_BIT)
+#define USART_CR2_CPOL_LOW (0x0 << USART_CR2_CLKEN_BIT)
+#define USART_CR2_CPOL_HIGH (0x1 << USART_CR2_CLKEN_BIT)
+/* Not on UART4, UART5 */
+#define USART_CR2_CPHA BIT(USART_CR2_CPHA_BIT)
+#define USART_CR2_CPHA_FIRST (0x0 << USART_CR2_CPHA_BIT)
+#define USART_CR2_CPHA_SECOND (0x1 << USART_CR2_CPHA_BIT)
+/* Not on UART4, UART5 */
+#define USART_CR2_LBCL BIT(USART_CR2_LBCL_BIT)
+#define USART_CR2_LBDIE BIT(USART_CR2_LBDIE_BIT)
+#define USART_CR2_LBDL BIT(USART_CR2_LBDL_BIT)
+#define USART_CR2_LBDL_10_BIT (0 << USART_CR2_LBDL_BIT)
+#define USART_CR2_LBDL_11_BIT (1 << USART_CR2_LBDL_BIT)
+#define USART_CR2_ADD 0xF
+
+/* Control register 3 */
+
+#define USART_CR3_CTSIE_BIT 10
+#define USART_CR3_CTSE_BIT 9
+#define USART_CR3_RTSE_BIT 8
+#define USART_CR3_DMAT_BIT 7
+#define USART_CR3_DMAR_BIT 6
+#define USART_CR3_SCEN_BIT 5
+#define USART_CR3_NACK_BIT 4
+#define USART_CR3_HDSEL_BIT 3
+#define USART_CR3_IRLP_BIT 2
+#define USART_CR3_IREN_BIT 1
+#define USART_CR3_EIE_BIT 0
+
+/* Not on UART4, UART5 */
+#define USART_CR3_CTSIE BIT(USART_CR3_CTSIE_BIT)
+/* Not on UART4, UART5 */
+#define USART_CR3_CTSE BIT(USART_CR3_CTSE_BIT)
+/* Not on UART4, UART5 */
+#define USART_CR3_RTSE BIT(USART_CR3_RTSE_BIT)
+/* Not on UART5 */
+#define USART_CR3_DMAT BIT(USART_CR3_DMAT_BIT)
+/* Not on UART5 */
+#define USART_CR3_DMAR BIT(USART_CR3_DMAR_BIT)
+/* Not on UART4, UART5 */
+#define USART_CR3_SCEN BIT(USART_CR3_SCEN_BIT)
+/* Not on UART4, UART5 */
+#define USART_CR3_NACK BIT(USART_CR3_NACK_BIT)
+#define USART_CR3_HDSEL BIT(USART_CR3_HDSEL_BIT)
+#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)
+#define USART_CR3_IREN BIT(USART_CR3_IREN_BIT)
+#define USART_CR3_EIE BIT(USART_CR3_EIE_BIT)
+
+/* Guard time and prescaler register */
+
+/* Not on UART4, UART5 */
+#define USART_GTPR_GT (0xFF << 8)
+/* Not on UART4, UART5 */
+#define USART_GTPR_PSC 0xFF
+
+/*
+ * Devices
+ */
+
+#define USART_RX_BUF_SIZE 64
+
+/** USART device type */
+typedef struct usart_dev {
+ usart_reg_map *regs;
+ ring_buffer *rb;
+ uint32 max_baud;
+ uint8 rx_buf[USART_RX_BUF_SIZE];
+ rcc_clk_id clk_id;
+ nvic_irq_num irq_num;
+} usart_dev;
+
+/** USART1 device */
+extern usart_dev *USART1;
+/** USART2 device */
+extern usart_dev *USART2;
+/** USART3 device */
+extern usart_dev *USART3;
+#ifdef STM32_HIGH_DENSITY
+/** UART4 device */
+extern usart_dev *UART4;
+/** UART5 device */
+extern usart_dev *UART5;
+#endif
+
+#ifdef STM32_MEDIUM_DENSITY
+#define NR_USARTS 3
+#elif defined(STM32_HIGH_DENSITY)
+#define NR_USARTS 5
+#else
+#warn "Only medium and high density devices are currently supported"
+#endif
+
+void usart_init(usart_dev *dev);
+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));
+void usart_putstr(usart_dev *dev, const char*);
+void usart_putudec(usart_dev *dev, uint32 val);
/**
- * @brief send one character on a usart
- * @param usart_num usart to send on
- * @param byte byte to send
+ * @brief Disable all serial ports.
*/
-static inline void usart_putc(uint8 usart_num, uint8 byte) {
- usart_port *port = usart_dev_table[usart_num].base;
+static inline void usart_disable_all(void) {
+ usart_foreach(usart_disable);
+}
- /* Wait for the buffer to empty */
- while ((port->SR & USART_TXE) == 0)
+/**
+ * @brief Transmit one character on a serial port.
+ * @param dev Serial port to send on.
+ * @param byte Byte to transmit.
+ */
+static inline void usart_putc(usart_dev* dev, uint8 byte) {
+ usart_reg_map *regs = dev->regs;
+
+ while ((regs->SR & USART_SR_TXE) == 0)
;
- port->DR = byte;
+ regs->DR = byte;
}
/**
- * @brief read one character from a usart
- * @param usart_num usart to read from
+ * @brief Read one character from a serial port.
+ *
+ * It's not safe to call this function if the serial port has no data
+ * available.
+ *
+ * @param dev Serial port to read from
* @return byte read
+ * @see usart_data_available()
*/
-static inline uint8 usart_getc(uint8 usart_num) {
- return rb_remove(&usart_dev_table[usart_num].rb);
+static inline uint8 usart_getc(usart_dev *dev) {
+ return rb_remove(dev->rb);
}
/**
- * @brief return the amount of data available in the rx buffer
- * @param usart_num which usart to check
- * @return number of bytes in the rx buffer
+ * @brief Return the amount of data available in a serial port's RX buffer.
+ * @param dev Serial port to check
+ * @return Number of bytes in dev's RX buffer.
*/
-static inline uint32 usart_data_available(uint8 usart_num) {
- return rb_full_count(&usart_dev_table[usart_num].rb);
+static inline uint32 usart_data_available(usart_dev *dev) {
+ return rb_full_count(dev->rb);
}
/**
- * @brief removes the contents of the rx fifo
- * @param usart_num which usart to reset
+ * @brief Discard the contents of a serial port's RX buffer.
+ * @param dev Serial port whose buffer to empty.
*/
-static inline void usart_reset_rx(uint8 usart_num) {
- rb_reset(&usart_dev_table[usart_num].rb);
+static inline void usart_reset_rx(usart_dev *dev) {
+ rb_reset(dev->rb);
}
-void usart_init(uint8 usart_num, uint32 baud);
-void usart_disable(uint8 usart_num);
-void usart_disable_all();
-void usart_putstr(uint8 usart_num, const char*);
-void usart_putudec(uint8 usart_num, uint32 val);
-
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/libmaple/util.c b/libmaple/util.c
index 77af5b8..4a234ae 100644
--- a/libmaple/util.c
+++ b/libmaple/util.c
@@ -24,7 +24,7 @@
/**
* @brief Utility procedures for debugging, mostly an error LED fade
- * and messages dumped over a uart for failed asserts.
+ * and messages dumped over a UART for failed asserts.
*/
#include "libmaple.h"
@@ -34,38 +34,38 @@
#include "adc.h"
#include "timer.h"
-/* Failed asserts send out a message on this USART. */
-#ifndef ERROR_USART_NUM
-#define ERROR_USART_NUM USART2
+/* Failed ASSERT()s send out a message using this USART config. */
+#ifndef ERROR_USART
+#define ERROR_USART USART2
+#define ERROR_USART_CLK_SPEED 72000000UL
#define ERROR_USART_BAUD 9600
#define ERROR_TX_PORT GPIOA
#define ERROR_TX_PIN 2
#endif
/* If you define ERROR_LED_PORT and ERROR_LED_PIN, then a failed
- assert will also throb an LED connected to that port an pin.
- FIXME this should work together with wirish somehow. */
+ * ASSERT() will also throb() an LED connected to that port and pin.
+ */
#if defined(ERROR_LED_PORT) && defined(ERROR_LED_PIN)
#define HAVE_ERROR_LED
#endif
/**
* @brief Disables all peripheral interrupts except USB and fades the
- * error LED.
- *
- * Called from exc.S with global interrupts disabled.
+ * error LED.
*/
+/* (Called from exc.S with global interrupts disabled.) */
void __error(void) {
/* Turn off peripheral interrupts */
nvic_irq_disable_all();
- /* Turn off timers */
+ /* Turn off timers */
timer_disable_all();
/* Turn off ADC */
adc_disable_all();
- /* Turn off all usarts */
+ /* Turn off all USARTs */
usart_disable_all();
/* Turn the USB interrupt back on so the bootloader keeps on functioning */
@@ -78,33 +78,33 @@ void __error(void) {
}
/**
- * @brief Prints an error message on a uart upon a failed assertion
- * and error throbs.
+ * @brief Print an error message on a UART upon a failed assertion
+ * and throb the error LED, if there is one defined.
* @param file Source file of failed assertion
* @param line Source line of failed assertion
* @param exp String representation of failed assertion
* @sideeffect Turns of all peripheral interrupts except USB.
*/
void _fail(const char* file, int line, const char* exp) {
- /* Initialize the error usart */
+ /* Initialize the error USART */
gpio_set_mode(ERROR_TX_PORT, ERROR_TX_PIN, GPIO_AF_OUTPUT_PP);
- usart_init(ERROR_USART_NUM, ERROR_USART_BAUD);
+ usart_init(ERROR_USART);
+ usart_set_baud_rate(ERROR_USART, ERROR_USART_CLK_SPEED, ERROR_USART_BAUD);
/* Print failed assert message */
- usart_putstr(ERROR_USART_NUM, "ERROR: FAILED ASSERT(");
- usart_putstr(ERROR_USART_NUM, exp);
- usart_putstr(ERROR_USART_NUM, "): ");
- usart_putstr(ERROR_USART_NUM, file);
- usart_putstr(ERROR_USART_NUM, ": ");
- usart_putudec(ERROR_USART_NUM, line);
- usart_putc(ERROR_USART_NUM, '\n');
- usart_putc(ERROR_USART_NUM, '\r');
+ usart_putstr(ERROR_USART, "ERROR: FAILED ASSERT(");
+ usart_putstr(ERROR_USART, exp);
+ usart_putstr(ERROR_USART, "): ");
+ usart_putstr(ERROR_USART, file);
+ usart_putstr(ERROR_USART, ": ");
+ usart_putudec(ERROR_USART, line);
+ usart_putc(ERROR_USART, '\n');
+ usart_putc(ERROR_USART, '\r');
/* Error fade */
__error();
}
-
/**
* @brief Fades the error LED on and off
* @sideeffect Sets output push-pull on ERROR_LED_PIN.
@@ -117,7 +117,7 @@ void throb(void) {
uint32 i = 0;
gpio_set_mode(ERROR_LED_PORT, ERROR_LED_PIN, GPIO_OUTPUT_PP);
- /* Error fade */
+ /* Error fade. */
while (1) {
if (CC == TOP_CNT) {
slope = -1;
@@ -138,9 +138,8 @@ void throb(void) {
i++;
}
#else
- /* No error LED is connected; do nothing. */
+ /* No error LED is defined; do nothing. */
while (1)
;
#endif
}
-