串口环形缓冲区强化:单独单写及最小临界区修改
This commit is contained in:
16
Inc/uart.h
16
Inc/uart.h
@@ -12,4 +12,20 @@
|
|||||||
void uart_init(void);
|
void uart_init(void);
|
||||||
void debug_usart_init(void);
|
void debug_usart_init(void);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief pause UART RX interrupt (RBNE)
|
||||||
|
\param[in] none
|
||||||
|
\param[out] none
|
||||||
|
\retval none
|
||||||
|
*/
|
||||||
|
void uart_rx_irq_pause(void);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief resume UART RX interrupt (RBNE)
|
||||||
|
\param[in] none
|
||||||
|
\param[out] none
|
||||||
|
\retval none
|
||||||
|
*/
|
||||||
|
void uart_rx_irq_resume(void);
|
||||||
|
|
||||||
#endif // UART_H
|
#endif // UART_H
|
||||||
|
|||||||
@@ -27,6 +27,12 @@
|
|||||||
* @section RingBuffer_Usage 使用说明
|
* @section RingBuffer_Usage 使用说明
|
||||||
* 典型用法:中断接收(写入环形缓冲)、主循环解析(读取环形缓冲)。
|
* 典型用法:中断接收(写入环形缓冲)、主循环解析(读取环形缓冲)。
|
||||||
*
|
*
|
||||||
|
* 并发访问约束(SPSC,无锁单写单读):
|
||||||
|
* - ISR 生产者:仅调用 uart_ring_buffer_put() 写入数据。
|
||||||
|
* - 主循环消费者:仅调用 uart_ring_buffer_get()/uart_ring_buffer_available() 读取数据。
|
||||||
|
* - uart_ring_buffer_init()/uart_ring_buffer_clear() 会同时修改读写索引,内部使用最小临界区保护。
|
||||||
|
* - 建议在主循环调用 clear/init 前先暂停 UART RX 中断,完成后再恢复,避免与 ISR 竞争。
|
||||||
|
*
|
||||||
* 1) 初始化
|
* 1) 初始化
|
||||||
* @code{.c}
|
* @code{.c}
|
||||||
* uart_ring_buffer_init();
|
* uart_ring_buffer_init();
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "uart_ring_buffer.h"
|
#include "uart_ring_buffer.h"
|
||||||
|
#include "uart.h"
|
||||||
#include "led.h"
|
#include "led.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@@ -588,7 +589,9 @@ void command_process(void) {
|
|||||||
handle_command(cmd_buf, expected_cmd_len);
|
handle_command(cmd_buf, expected_cmd_len);
|
||||||
} else {
|
} else {
|
||||||
// 验证失败时清空缓冲区,避免后续帧受影响
|
// 验证失败时清空缓冲区,避免后续帧受影响
|
||||||
|
uart_rx_irq_pause();
|
||||||
uart_ring_buffer_clear();
|
uart_ring_buffer_clear();
|
||||||
|
uart_rx_irq_resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 复位,等待下一帧
|
// 复位,等待下一帧
|
||||||
@@ -633,7 +636,9 @@ void command_execute(const char *cmd_str)
|
|||||||
frame_buf[frame_len - 1] = (uint8_t)(crc & 0xFF);
|
frame_buf[frame_len - 1] = (uint8_t)(crc & 0xFF);
|
||||||
|
|
||||||
// 清空缓冲区并执行命令
|
// 清空缓冲区并执行命令
|
||||||
|
uart_rx_irq_pause();
|
||||||
uart_ring_buffer_clear();
|
uart_ring_buffer_clear();
|
||||||
|
uart_rx_irq_resume();
|
||||||
for (uint8_t i = 0; i < frame_len; i++) {
|
for (uint8_t i = 0; i < frame_len; i++) {
|
||||||
uart_ring_buffer_put(frame_buf[i]);
|
uart_ring_buffer_put(frame_buf[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,14 @@ void uart_init(void) {
|
|||||||
usart_interrupt_enable(UART_PHY, USART_INT_RBNE);
|
usart_interrupt_enable(UART_PHY, USART_INT_RBNE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void uart_rx_irq_pause(void) {
|
||||||
|
usart_interrupt_disable(UART_PHY, USART_INT_RBNE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_rx_irq_resume(void) {
|
||||||
|
usart_interrupt_enable(UART_PHY, USART_INT_RBNE);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* 具体的中断处理函数实现 */
|
/* 具体的中断处理函数实现 */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|||||||
@@ -6,12 +6,25 @@
|
|||||||
* @ingroup RingBuffer
|
* @ingroup RingBuffer
|
||||||
*/
|
*/
|
||||||
#include "uart_ring_buffer.h"
|
#include "uart_ring_buffer.h"
|
||||||
|
#include "gd32e23x.h"
|
||||||
|
|
||||||
static volatile uint8_t uart_rx_buffer[UART_RX_BUFFER_SIZE];
|
static volatile uint8_t uart_rx_buffer[UART_RX_BUFFER_SIZE];
|
||||||
static volatile uint8_t write_index = 0;
|
static volatile uint8_t write_index = 0;
|
||||||
static volatile uint8_t read_index = 0;
|
static volatile uint8_t read_index = 0;
|
||||||
static volatile uint32_t dropped_bytes = 0;
|
static volatile uint32_t dropped_bytes = 0;
|
||||||
|
|
||||||
|
static inline uint32_t irq_save(void) {
|
||||||
|
uint32_t primask = __get_PRIMASK();
|
||||||
|
__disable_irq();
|
||||||
|
return primask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void irq_restore(uint32_t primask) {
|
||||||
|
if (primask == 0U) {
|
||||||
|
__enable_irq();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 重置环形缓冲区状态。
|
* @brief 重置环形缓冲区状态。
|
||||||
* @details 将读指针、写指针与丢弃计数清零,不清空数据区内容。
|
* @details 将读指针、写指针与丢弃计数清零,不清空数据区内容。
|
||||||
@@ -31,7 +44,9 @@ static void uart_ring_buffer_reset_state(void) {
|
|||||||
* @ingroup RingBuffer
|
* @ingroup RingBuffer
|
||||||
*/
|
*/
|
||||||
void uart_ring_buffer_init(void) {
|
void uart_ring_buffer_init(void) {
|
||||||
|
uint32_t irq_key = irq_save();
|
||||||
uart_ring_buffer_reset_state();
|
uart_ring_buffer_reset_state();
|
||||||
|
irq_restore(irq_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,7 +105,9 @@ bool uart_ring_buffer_put(uint8_t data) {
|
|||||||
* @ingroup RingBuffer
|
* @ingroup RingBuffer
|
||||||
*/
|
*/
|
||||||
void uart_ring_buffer_clear(void) {
|
void uart_ring_buffer_clear(void) {
|
||||||
|
uint32_t irq_key = irq_save();
|
||||||
uart_ring_buffer_reset_state();
|
uart_ring_buffer_reset_state();
|
||||||
|
irq_restore(irq_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user