Skip to content

Commit 51d2d9e

Browse files
committed
F1 USART - buffered interrupt-based TX (static TX buffer)
usart.h: statically define TX buffer like RX buffer. TX buffer size defined in USART_TX_BUF_SIZE usart.h: add function usart_reset_tx() to reset TX buffer (same as for RX bufferI) usart.c: usart_init() changed to init TX buffer usart.c: usart_disable() changed to reset TX buffer usart.c: usart_tx() changed to use TX buffer and manage interrupt TXEIE usart_f1.c: changed to instantiate TX buffers usart_private.h: changed interrupt handler to manage TXEIE
1 parent ea6ec1d commit 51d2d9e

4 files changed

Lines changed: 53 additions & 10 deletions

File tree

STM32F1/cores/maple/libmaple/usart.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
*/
4141
void usart_init(usart_dev *dev) {
4242
rb_init(dev->rb, USART_RX_BUF_SIZE, dev->rx_buf);
43+
rb_init(dev->wb, USART_TX_BUF_SIZE, dev->tx_buf);
4344
rcc_clk_enable(dev->clk_id);
4445
nvic_irq_enable(dev->irq_num);
4546
}
@@ -78,6 +79,7 @@ void usart_disable(usart_dev *dev) {
7879

7980
/* Clean up buffer */
8081
usart_reset_rx(dev);
82+
usart_reset_tx(dev);
8183
}
8284

8385
/**
@@ -90,9 +92,20 @@ void usart_disable(usart_dev *dev) {
9092
uint32 usart_tx(usart_dev *dev, const uint8 *buf, uint32 len) {
9193
usart_reg_map *regs = dev->regs;
9294
uint32 txed = 0;
93-
while ((regs->SR & USART_SR_TXE) && (txed < len)) {
95+
while (rb_is_empty(dev->wb) && (regs->SR & USART_SR_TXE) && (txed < len)) {
9496
regs->DR = buf[txed++];
9597
}
98+
regs->CR1 &= ~((uint32)USART_CR1_TXEIE); // disable TXEIE while populating the buffer
99+
while (txed < len) {
100+
if (rb_safe_insert(dev->wb, buf[txed])) {
101+
txed++;
102+
}
103+
else
104+
break;
105+
}
106+
if (rb_full_count(dev->wb) > 0) {
107+
regs->CR1 |= USART_CR1_TXEIE;
108+
}
96109
return txed;
97110
}
98111

STM32F1/cores/maple/libmaple/usart_f1.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@
4141
*/
4242

4343
static ring_buffer usart1_rb;
44+
static ring_buffer usart1_wb;
4445
static usart_dev usart1 = {
4546
.regs = USART1_BASE,
4647
.rb = &usart1_rb,
48+
.wb = &usart1_wb,
4749
.max_baud = 4500000UL,
4850
.clk_id = RCC_USART1,
4951
.irq_num = NVIC_USART1,
@@ -52,9 +54,11 @@ static usart_dev usart1 = {
5254
usart_dev *USART1 = &usart1;
5355

5456
static ring_buffer usart2_rb;
57+
static ring_buffer usart2_wb;
5558
static usart_dev usart2 = {
5659
.regs = USART2_BASE,
5760
.rb = &usart2_rb,
61+
.wb = &usart2_wb,
5862
.max_baud = 2250000UL,
5963
.clk_id = RCC_USART2,
6064
.irq_num = NVIC_USART2,
@@ -63,9 +67,11 @@ static usart_dev usart2 = {
6367
usart_dev *USART2 = &usart2;
6468

6569
static ring_buffer usart3_rb;
70+
static ring_buffer usart3_wb;
6671
static usart_dev usart3 = {
6772
.regs = USART3_BASE,
6873
.rb = &usart3_rb,
74+
.wb = &usart3_wb,
6975
.max_baud = 2250000UL,
7076
.clk_id = RCC_USART3,
7177
.irq_num = NVIC_USART3,
@@ -75,9 +81,11 @@ usart_dev *USART3 = &usart3;
7581

7682
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
7783
static ring_buffer uart4_rb;
84+
static ring_buffer uart4_wb;
7885
static usart_dev uart4 = {
7986
.regs = UART4_BASE,
8087
.rb = &uart4_rb,
88+
.wb = &uart4_wb,
8189
.max_baud = 2250000UL,
8290
.clk_id = RCC_UART4,
8391
.irq_num = NVIC_UART4,
@@ -86,9 +94,11 @@ static usart_dev uart4 = {
8694
usart_dev *UART4 = &uart4;
8795

8896
static ring_buffer uart5_rb;
97+
static ring_buffer uart5_wb;
8998
static usart_dev uart5 = {
9099
.regs = UART5_BASE,
91100
.rb = &uart5_rb,
101+
.wb = &uart5_wb,
92102
.max_baud = 2250000UL,
93103
.clk_id = RCC_UART5,
94104
.irq_num = NVIC_UART5,
@@ -191,23 +201,23 @@ void usart_foreach(void (*fn)(usart_dev*)) {
191201
*/
192202

193203
void __irq_usart1(void) {
194-
usart_irq(&usart1_rb, USART1_BASE);
204+
usart_irq(&usart1_rb, &usart1_wb, USART1_BASE);
195205
}
196206

197207
void __irq_usart2(void) {
198-
usart_irq(&usart2_rb, USART2_BASE);
208+
usart_irq(&usart2_rb, &usart2_wb, USART2_BASE);
199209
}
200210

201211
void __irq_usart3(void) {
202-
usart_irq(&usart3_rb, USART3_BASE);
212+
usart_irq(&usart3_rb, &usart3_wb, USART3_BASE);
203213
}
204214

205215
#ifdef STM32_HIGH_DENSITY
206216
void __irq_uart4(void) {
207-
usart_irq(&uart4_rb, UART4_BASE);
217+
usart_irq(&uart4_rb, &uart4_wb, UART4_BASE);
208218
}
209219

210220
void __irq_uart5(void) {
211-
usart_irq(&uart5_rb, UART5_BASE);
221+
usart_irq(&uart5_rb, &uart5_wb, UART5_BASE);
212222
}
213223
#endif

STM32F1/system/libmaple/include/libmaple/usart.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,16 +381,22 @@ typedef struct usart_reg_map {
381381
#define USART_RX_BUF_SIZE 64
382382
#endif
383383

384+
#ifndef USART_TX_BUF_SIZE
385+
#define USART_TX_BUF_SIZE 64
386+
#endif
387+
384388
/** USART device type */
385389
typedef struct usart_dev {
386390
usart_reg_map *regs; /**< Register map */
387391
ring_buffer *rb; /**< RX ring buffer */
392+
ring_buffer *wb; /**< TX ring buffer */
388393
uint32 max_baud; /**< @brief Deprecated.
389394
* Maximum baud rate. */
390395
uint8 rx_buf[USART_RX_BUF_SIZE]; /**< @brief Deprecated.
391396
* Actual RX buffer used by rb.
392397
* This field will be removed in
393398
* a future release. */
399+
uint8 tx_buf[USART_TX_BUF_SIZE]; /* Actual TX buffer used by wb */
394400
rcc_clk_id clk_id; /**< RCC clock information */
395401
nvic_irq_num irq_num; /**< USART NVIC interrupt */
396402
} usart_dev;
@@ -502,6 +508,14 @@ static inline void usart_reset_rx(usart_dev *dev) {
502508
rb_reset(dev->rb);
503509
}
504510

511+
/**
512+
* @brief Discard the contents of a serial port's RX buffer.
513+
* @param dev Serial port whose buffer to empty.
514+
*/
515+
static inline void usart_reset_tx(usart_dev *dev) {
516+
rb_reset(dev->wb);
517+
}
518+
505519
#ifdef __cplusplus
506520
} // extern "C"
507521
#endif

STM32F1/system/libmaple/usart_private.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@
3737
#include <libmaple/ring_buffer.h>
3838
#include <libmaple/usart.h>
3939

40-
static inline __always_inline void usart_irq(ring_buffer *rb, usart_reg_map *regs) {
41-
/* We can get RXNE and ORE interrupts here. Only RXNE signifies
42-
* availability of a byte in DR.
40+
static inline __always_inline void usart_irq(ring_buffer *rb, ring_buffer *wb, usart_reg_map *regs) {
41+
/* Handling RXNEIE and TXEIE interrupts.
42+
* RXNE signifies availability of a byte in DR.
4343
*
4444
* See table 198 (sec 27.4, p809) in STM document RM0008 rev 15.
4545
* We enable RXNEIE. */
46-
if (regs->SR & USART_SR_RXNE) {
46+
if ((regs->CR1 & USART_CR1_RXNEIE) && (regs->SR & USART_SR_RXNE)) {
4747
#ifdef USART_SAFE_INSERT
4848
/* If the buffer is full and the user defines USART_SAFE_INSERT,
4949
* ignore new bytes. */
@@ -53,6 +53,12 @@ static inline __always_inline void usart_irq(ring_buffer *rb, usart_reg_map *reg
5353
rb_push_insert(rb, (uint8)regs->DR);
5454
#endif
5555
}
56+
/* TXE signifies readiness to send a byte to DR. */
57+
if ((regs->CR1 & USART_CR1_TXEIE) && (regs->SR & USART_SR_TXE)) {
58+
regs->DR=rb_remove(wb);
59+
if (rb_is_empty(wb))
60+
regs->CR1 &= ~((uint32)USART_CR1_TXEIE); // disable TXEIE
61+
}
5662
}
5763

5864
uint32 _usart_clock_freq(usart_dev *dev);

0 commit comments

Comments
 (0)