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
This commit is contained in:
parent
ea6ec1d0aa
commit
51d2d9e0d9
|
@ -40,6 +40,7 @@
|
|||
*/
|
||||
void usart_init(usart_dev *dev) {
|
||||
rb_init(dev->rb, USART_RX_BUF_SIZE, dev->rx_buf);
|
||||
rb_init(dev->wb, USART_TX_BUF_SIZE, dev->tx_buf);
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
nvic_irq_enable(dev->irq_num);
|
||||
}
|
||||
|
@ -78,6 +79,7 @@ void usart_disable(usart_dev *dev) {
|
|||
|
||||
/* Clean up buffer */
|
||||
usart_reset_rx(dev);
|
||||
usart_reset_tx(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,9 +92,20 @@ void usart_disable(usart_dev *dev) {
|
|||
uint32 usart_tx(usart_dev *dev, const uint8 *buf, uint32 len) {
|
||||
usart_reg_map *regs = dev->regs;
|
||||
uint32 txed = 0;
|
||||
while ((regs->SR & USART_SR_TXE) && (txed < len)) {
|
||||
while (rb_is_empty(dev->wb) && (regs->SR & USART_SR_TXE) && (txed < len)) {
|
||||
regs->DR = buf[txed++];
|
||||
}
|
||||
regs->CR1 &= ~((uint32)USART_CR1_TXEIE); // disable TXEIE while populating the buffer
|
||||
while (txed < len) {
|
||||
if (rb_safe_insert(dev->wb, buf[txed])) {
|
||||
txed++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (rb_full_count(dev->wb) > 0) {
|
||||
regs->CR1 |= USART_CR1_TXEIE;
|
||||
}
|
||||
return txed;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,9 +41,11 @@
|
|||
*/
|
||||
|
||||
static ring_buffer usart1_rb;
|
||||
static ring_buffer usart1_wb;
|
||||
static usart_dev usart1 = {
|
||||
.regs = USART1_BASE,
|
||||
.rb = &usart1_rb,
|
||||
.wb = &usart1_wb,
|
||||
.max_baud = 4500000UL,
|
||||
.clk_id = RCC_USART1,
|
||||
.irq_num = NVIC_USART1,
|
||||
|
@ -52,9 +54,11 @@ static usart_dev usart1 = {
|
|||
usart_dev *USART1 = &usart1;
|
||||
|
||||
static ring_buffer usart2_rb;
|
||||
static ring_buffer usart2_wb;
|
||||
static usart_dev usart2 = {
|
||||
.regs = USART2_BASE,
|
||||
.rb = &usart2_rb,
|
||||
.wb = &usart2_wb,
|
||||
.max_baud = 2250000UL,
|
||||
.clk_id = RCC_USART2,
|
||||
.irq_num = NVIC_USART2,
|
||||
|
@ -63,9 +67,11 @@ static usart_dev usart2 = {
|
|||
usart_dev *USART2 = &usart2;
|
||||
|
||||
static ring_buffer usart3_rb;
|
||||
static ring_buffer usart3_wb;
|
||||
static usart_dev usart3 = {
|
||||
.regs = USART3_BASE,
|
||||
.rb = &usart3_rb,
|
||||
.wb = &usart3_wb,
|
||||
.max_baud = 2250000UL,
|
||||
.clk_id = RCC_USART3,
|
||||
.irq_num = NVIC_USART3,
|
||||
|
@ -75,9 +81,11 @@ usart_dev *USART3 = &usart3;
|
|||
|
||||
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
static ring_buffer uart4_rb;
|
||||
static ring_buffer uart4_wb;
|
||||
static usart_dev uart4 = {
|
||||
.regs = UART4_BASE,
|
||||
.rb = &uart4_rb,
|
||||
.wb = &uart4_wb,
|
||||
.max_baud = 2250000UL,
|
||||
.clk_id = RCC_UART4,
|
||||
.irq_num = NVIC_UART4,
|
||||
|
@ -86,9 +94,11 @@ static usart_dev uart4 = {
|
|||
usart_dev *UART4 = &uart4;
|
||||
|
||||
static ring_buffer uart5_rb;
|
||||
static ring_buffer uart5_wb;
|
||||
static usart_dev uart5 = {
|
||||
.regs = UART5_BASE,
|
||||
.rb = &uart5_rb,
|
||||
.wb = &uart5_wb,
|
||||
.max_baud = 2250000UL,
|
||||
.clk_id = RCC_UART5,
|
||||
.irq_num = NVIC_UART5,
|
||||
|
@ -191,23 +201,23 @@ void usart_foreach(void (*fn)(usart_dev*)) {
|
|||
*/
|
||||
|
||||
void __irq_usart1(void) {
|
||||
usart_irq(&usart1_rb, USART1_BASE);
|
||||
usart_irq(&usart1_rb, &usart1_wb, USART1_BASE);
|
||||
}
|
||||
|
||||
void __irq_usart2(void) {
|
||||
usart_irq(&usart2_rb, USART2_BASE);
|
||||
usart_irq(&usart2_rb, &usart2_wb, USART2_BASE);
|
||||
}
|
||||
|
||||
void __irq_usart3(void) {
|
||||
usart_irq(&usart3_rb, USART3_BASE);
|
||||
usart_irq(&usart3_rb, &usart3_wb, USART3_BASE);
|
||||
}
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
void __irq_uart4(void) {
|
||||
usart_irq(&uart4_rb, UART4_BASE);
|
||||
usart_irq(&uart4_rb, &uart4_wb, UART4_BASE);
|
||||
}
|
||||
|
||||
void __irq_uart5(void) {
|
||||
usart_irq(&uart5_rb, UART5_BASE);
|
||||
usart_irq(&uart5_rb, &uart5_wb, UART5_BASE);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -381,16 +381,22 @@ typedef struct usart_reg_map {
|
|||
#define USART_RX_BUF_SIZE 64
|
||||
#endif
|
||||
|
||||
#ifndef USART_TX_BUF_SIZE
|
||||
#define USART_TX_BUF_SIZE 64
|
||||
#endif
|
||||
|
||||
/** USART device type */
|
||||
typedef struct usart_dev {
|
||||
usart_reg_map *regs; /**< Register map */
|
||||
ring_buffer *rb; /**< RX ring buffer */
|
||||
ring_buffer *wb; /**< TX ring buffer */
|
||||
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
|
||||
* a future release. */
|
||||
uint8 tx_buf[USART_TX_BUF_SIZE]; /* Actual TX buffer used by wb */
|
||||
rcc_clk_id clk_id; /**< RCC clock information */
|
||||
nvic_irq_num irq_num; /**< USART NVIC interrupt */
|
||||
} usart_dev;
|
||||
|
@ -502,6 +508,14 @@ static inline void usart_reset_rx(usart_dev *dev) {
|
|||
rb_reset(dev->rb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Discard the contents of a serial port's RX buffer.
|
||||
* @param dev Serial port whose buffer to empty.
|
||||
*/
|
||||
static inline void usart_reset_tx(usart_dev *dev) {
|
||||
rb_reset(dev->wb);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
@ -37,13 +37,13 @@
|
|||
#include <libmaple/ring_buffer.h>
|
||||
#include <libmaple/usart.h>
|
||||
|
||||
static inline __always_inline void usart_irq(ring_buffer *rb, usart_reg_map *regs) {
|
||||
/* We can get RXNE and ORE interrupts here. Only RXNE signifies
|
||||
* availability of a byte in DR.
|
||||
static inline __always_inline void usart_irq(ring_buffer *rb, ring_buffer *wb, usart_reg_map *regs) {
|
||||
/* Handling RXNEIE and TXEIE interrupts.
|
||||
* RXNE signifies availability of a byte in DR.
|
||||
*
|
||||
* See table 198 (sec 27.4, p809) in STM document RM0008 rev 15.
|
||||
* We enable RXNEIE. */
|
||||
if (regs->SR & USART_SR_RXNE) {
|
||||
if ((regs->CR1 & USART_CR1_RXNEIE) && (regs->SR & USART_SR_RXNE)) {
|
||||
#ifdef USART_SAFE_INSERT
|
||||
/* If the buffer is full and the user defines USART_SAFE_INSERT,
|
||||
* ignore new bytes. */
|
||||
|
@ -53,6 +53,12 @@ static inline __always_inline void usart_irq(ring_buffer *rb, usart_reg_map *reg
|
|||
rb_push_insert(rb, (uint8)regs->DR);
|
||||
#endif
|
||||
}
|
||||
/* TXE signifies readiness to send a byte to DR. */
|
||||
if ((regs->CR1 & USART_CR1_TXEIE) && (regs->SR & USART_SR_TXE)) {
|
||||
regs->DR=rb_remove(wb);
|
||||
if (rb_is_empty(wb))
|
||||
regs->CR1 &= ~((uint32)USART_CR1_TXEIE); // disable TXEIE
|
||||
}
|
||||
}
|
||||
|
||||
uint32 _usart_clock_freq(usart_dev *dev);
|
||||
|
|
Loading…
Reference in New Issue