aboutsummaryrefslogtreecommitdiffstats
path: root/libmaple/usart.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmaple/usart.c')
-rw-r--r--libmaple/usart.c316
1 files changed, 77 insertions, 239 deletions
diff --git a/libmaple/usart.c b/libmaple/usart.c
index 282fc5d..d08d3cf 100644
--- a/libmaple/usart.c
+++ b/libmaple/usart.c
@@ -36,123 +36,95 @@
#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_TXE BIT(7)
#define USART_TC BIT(6)
-#define USART_STOP_BITS_1 BIT_MASK_SHIFT(0b0, 12)
-#define USART_STOP_BITS_05 BIT_MASK_SHIFT(0b01, 12)
-#define USART_STOP_BITS_2 BIT_MASK_SHIFT(0b02, 12)
-#define USART_STOP_BITS_15 BIT_MASK_SHIFT(0b02, 12)
-
-#define USART1_CLK 72000000UL
-#define USART2_CLK 36000000UL
-#define USART3_CLK 36000000UL
-
-#define USART_RECV_BUF_SIZE 64
-
-/* Ring buffer notes:
- * The buffer is empty when head == tail.
- * The buffer is full when the head is one byte in front of the tail
- * The total buffer size must be a power of two
- * Note, one byte is necessarily left free with this scheme */
-typedef struct usart_ring_buf {
- uint32 head;
- uint32 tail;
- uint8 buf[USART_RECV_BUF_SIZE];
-} usart_ring_buf;
-
-static usart_ring_buf ring_buf1;
-static usart_ring_buf ring_buf2;
-static usart_ring_buf ring_buf3;
-
-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 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
+ },
+ #if NR_USART >= 5
+ [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 */
void USART1_IRQHandler(void) {
- /* Read the data */
- ring_buf1.buf[ring_buf1.tail++] = (uint8)(((usart_port*)(USART1_BASE))->DR);
- ring_buf1.tail %= USART_RECV_BUF_SIZE;
+ rb_insert(&(usart_dev_table[USART1].rb), (uint8)(((usart_port*)(USART1_BASE))->DR));
}
-/* Don't overrun your buffer, seriously */
void USART2_IRQHandler(void) {
- /* Read the data */
- ring_buf2.buf[ring_buf2.tail++] = (uint8)(((usart_port*)(USART2_BASE))->DR);
- ring_buf2.tail %= USART_RECV_BUF_SIZE;
+ rb_insert(&(usart_dev_table[USART2].rb), (uint8)(((usart_port*)(USART2_BASE))->DR));
}
-/* Don't overrun your buffer, seriously */
+
void USART3_IRQHandler(void) {
- /* Read the data */
- ring_buf3.buf[ring_buf3.tail++] = (uint8)(((usart_port*)(USART3_BASE))->DR);
- ring_buf3.tail %= USART_RECV_BUF_SIZE;
+ rb_insert(&usart_dev_table[USART3].rb, (uint8)(((usart_port*)(USART3_BASE))->DR));
+}
+#if NR_USART >= 5
+void UART4_IRQHandler(void) {
+ rb_insert(&usart_dev_table[UART4].rb, (uint8)(((usart_port*)(UART4_BASE))->DR));
}
+void UART5_IRQHandler(void) {
+ rb_insert(&usart_dev_table[UART5].rb, (uint8)(((usart_port*)(UART5_BASE))->DR));
+}
+#endif
/**
* @brief Enable a USART in single buffer transmission mode, multibuffer
- * receiver mode.
- *
+ * receiver mode.
* @param usart_num USART to be initialized
* @param baud Baud rate to be set at
- * @param recvBuf buf buffer for receiver
- * @param len size of recvBuf
- *
- * @sideeffect Turns on the specified USART
*/
void usart_init(uint8 usart_num, uint32 baud) {
- ASSERT((usart_num <= NR_USARTS) && (usart_num > 0));
- ASSERT(baud && (baud < USART_MAX_BAUD));
-
+ ASSERT(usart_num <= NR_USART);
usart_port *port;
- usart_ring_buf *ring_buf;
+ ring_buffer *ring_buf;
uint32 clk_speed;
uint32 integer_part;
uint32 fractional_part;
uint32 tmp;
- switch (usart_num) {
- case 1:
- port = (usart_port*)USART1_BASE;
- ring_buf = &ring_buf1;
- clk_speed = USART1_CLK;
- rcc_enable_clk_usart1();
- REG_SET(NVIC_ISER1, BIT(5));
- break;
- case 2:
- port = (usart_port*)USART2_BASE;
- ring_buf = &ring_buf2;
- clk_speed = USART2_CLK;
- rcc_enable_clk_usart2();
- REG_SET(NVIC_ISER1, BIT(6));
- break;
- case 3:
- port = (usart_port*)USART3_BASE;
- ring_buf = &ring_buf3;
- clk_speed = USART3_CLK;
- rcc_enable_clk_usart3();
- REG_SET(NVIC_ISER1, BIT(7));
- break;
- default:
- /* should never get here */
- ASSERT(0);
- }
+ 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 ring buffer */
- ring_buf->head = 0;
- ring_buf->tail = 0;
+ /* 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));
@@ -172,36 +144,25 @@ void usart_init(uint8 usart_num, uint32 baud) {
port->CR1 |= USART_UE;
}
+/**
+ * @brief Turn off all USARTs.
+ */
+void usart_disable_all() {
+ usart_disable(1);
+ usart_disable(2);
+ usart_disable(3);
+ #if NR_USART >= 5
+ usart_disable(4);
+ usart_disable(5);
+ #endif
+}
/**
* @brief Turn off a USART.
- *
* @param USART to be disabled
- *
- * @sideeffect Turns off the specified USART
*/
void usart_disable(uint8 usart_num) {
- ASSERT((usart_num <= NR_USARTS) && (usart_num > 0));
- usart_port *port;
-
- switch (usart_num) {
- case 1:
- port = (usart_port*)USART1_BASE;
- break;
- case 2:
- port = (usart_port*)USART2_BASE;
- break;
- case 3:
- port = (usart_port*)USART3_BASE;
- break;
- default:
- /* should never get here */
- ASSERT(0);
- }
-
- /* Is this usart enabled? */
- if (!(port->SR & USART_UE))
- return;
+ usart_port *port = usart_dev_table[usart_num].base;
/* TC bit must be high before disabling the usart */
while ((port->SR & USART_TC) == 0)
@@ -211,18 +172,17 @@ void usart_disable(uint8 usart_num) {
port->CR1 = 0;
/* Clean up buffer */
- usart_clear_buffer(usart_num);
+ usart_reset_rx(usart_num);
}
/**
* @brief Print a null terminated string to the specified USART
*
- * @param[in] usart_num USART to send on
- * @param[in] str String to send
+ * @param usart_num usart to send on
+ * @param str string to send
*/
void usart_putstr(uint8 usart_num, const char* str) {
- ASSERT((usart_num <= NR_USARTS) && (usart_num > 0));
char ch;
while((ch = *(str++)) != '\0') {
@@ -233,11 +193,10 @@ void usart_putstr(uint8 usart_num, const char* str) {
/**
* @brief Print an unsigned integer to the specified usart
*
- * @param[in] usart_num usart to send on
- * @param[in] val number to print
+ * @param usart_num usart to send on
+ * @param val number to print
*/
void usart_putudec(uint8 usart_num, uint32 val) {
- ASSERT((usart_num <= NR_USARTS) && (usart_num > 0));
char digits[12];
int i;
@@ -249,125 +208,4 @@ void usart_putudec(uint8 usart_num, uint32 val) {
while (--i >= 0) {
usart_putc(usart_num, digits[i]);
}
-
-}
-
-
-/**
- * @brief Return one character from the receive buffer. Assumes
- * that there is data available.
- *
- * @param[in] usart_num number of the usart to read from
- *
- * @return character from ring buffer
- *
- * @sideeffect may update the head pointer of the recv buffer
- */
-uint8 usart_getc(uint8 usart_num) {
- uint8 ch;
- usart_ring_buf *rb;
-
- switch (usart_num) {
- case 1:
- rb = &ring_buf1;
- break;
- case 2:
- rb = &ring_buf2;
- break;
- case 3:
- rb = &ring_buf3;
- break;
- default:
- ASSERT(0);
- }
-
- /* Make sure there's actually data to be read */
- ASSERT(rb->head != rb->tail);
-
- /* Read the data and check for wraparound */
- ch = rb->buf[rb->head++];
- rb->head %= USART_RECV_BUF_SIZE;
-
- return ch;
-}
-
-uint32 usart_data_available(uint8 usart_num) {
- usart_ring_buf *rb;
-
- switch (usart_num) {
- case 1:
- rb = &ring_buf1;
- break;
- case 2:
- rb = &ring_buf2;
- break;
- case 3:
- rb = &ring_buf3;
- break;
- default:
- ASSERT(0);
- }
-
- return rb->tail - rb->head;
-}
-
-void usart_clear_buffer(uint8 usart_num) {
- usart_ring_buf *rb;
-
- switch (usart_num) {
- case 1:
- rb = &ring_buf1;
- break;
- case 2:
- rb = &ring_buf2;
- break;
- case 3:
- rb = &ring_buf3;
- break;
- default:
- ASSERT(0);
- }
-
- rb->tail = rb->head;
-}
-
-
-
-/**
- * @brief Output a byte out the uart
- *
- * @param[in] usart_num usart number to output on
- * @param[in] byte byte to send
- *
- */
-void usart_putc(uint8 usart_num, uint8 byte) {
- ASSERT((usart_num <= NR_USARTS) && (usart_num > 0));
- usart_port *port;
-
- switch (usart_num) {
- case 1:
- port = (usart_port*)USART1_BASE;
- break;
- case 2:
- port = (usart_port*)USART2_BASE;
- break;
- case 3:
- port = (usart_port*)USART3_BASE;
- break;
- default:
- /* Should never get here */
- ASSERT(0);
- }
-
-// if (ch == '\n') {
-// usart_putc(usart_num, '\r');
-// }
-
- port->DR = byte;
-
- /* Wait for transmission to complete */
- while ((port->SR & USART_TXE) == 0)
- ;
}
-
-