|
|
@@ -1,82 +1,12 @@
|
|
|
#include "board.h"
|
|
|
#include "hard_hdma_int.h"
|
|
|
-#include "hpm_uart_drv.h"
|
|
|
-#include "hpm_dmamux_drv.h"
|
|
|
-#include "hpm_dma_drv.h"
|
|
|
-#include "hpm_gpio_drv.h"
|
|
|
+#include "my_board.h"
|
|
|
#include "hpm_clock_drv.h"
|
|
|
+#include "drv_usart.h"
|
|
|
#include "rkfifo.h"
|
|
|
+#include "test.h"
|
|
|
#include <string.h>
|
|
|
|
|
|
-/* ========== 配置宏定义 ========== */
|
|
|
-#ifndef UART_RX_FIFO_BUFFER_LEN
|
|
|
-#define UART_RX_FIFO_BUFFER_LEN 256
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifndef UART_TX_FIFO_BUFFER_LEN
|
|
|
-#define UART_TX_FIFO_BUFFER_LEN 256
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifndef UART_TX_DMA_BUFFER_LEN
|
|
|
-#define UART_TX_DMA_BUFFER_LEN 1024
|
|
|
-#endif
|
|
|
-
|
|
|
-/* ========== 外部DMA完成标志声明 ========== */
|
|
|
-extern bool uart1_tx_dma_done;
|
|
|
-extern bool uart2_tx_dma_done;
|
|
|
-extern bool uart3_tx_dma_done;
|
|
|
-extern bool uart4_tx_dma_done;
|
|
|
-extern bool uart5_tx_dma_done;
|
|
|
-extern bool uart6_tx_dma_done;
|
|
|
-
|
|
|
-/* ========== 结构体定义 ========== */
|
|
|
-struct _uart_config {
|
|
|
- UART_Type *uart_base; /* UART基地址 */
|
|
|
- uart_intr_enable_t uart_irq_mask; /* UART中断掩码 */
|
|
|
- uint8_t uart_irq_num; /* 中断号 */
|
|
|
-
|
|
|
- /* GPIO配置 */
|
|
|
- uint8_t tx_port; /* TX端口: 0-9 (GPIOA-GPIOJ) */
|
|
|
- uint8_t tx_pin; /* TX引脚 */
|
|
|
- uint8_t rx_port; /* RX端口 */
|
|
|
- uint8_t rx_pin; /* RX引脚 */
|
|
|
- uint8_t tx_af; /* TX复用功能 */
|
|
|
- uint8_t rx_af; /* RX复用功能 */
|
|
|
-
|
|
|
- /* DMA配置 */
|
|
|
- DMA_Type *dma_base; /* DMA控制器基地址 */
|
|
|
- DMAMUX_Type *dma_mux_base; /* DMA MUX */
|
|
|
- uint8_t dma_enable; /* DMA 使能 (修正拼写) */
|
|
|
- uint8_t dma_channel; /* DMA通道 */
|
|
|
- uint8_t dma_irq_num; /* DMA中断号 */
|
|
|
- uint8_t dma_request; /* DMA请求源 */
|
|
|
-
|
|
|
- /* 缓冲区 */
|
|
|
- uint8_t *tx_fifo_buff; /* TX FIFO缓冲区 */
|
|
|
- uint32_t tx_fifo_buff_size; /* TX FIFO大小 */
|
|
|
- uint8_t *rx_fifo_buff; /* RX FIFO缓冲区 */
|
|
|
- uint32_t rx_fifo_buff_size; /* RX FIFO大小 */
|
|
|
-
|
|
|
- /* DMA缓冲区 */
|
|
|
- uint8_t *dma_tx_buff; /* DMA发送缓冲区 */
|
|
|
- uint32_t dma_tx_buff_size; /* DMA发送缓冲区大小 */
|
|
|
-
|
|
|
- /* 内部使用 */
|
|
|
- rkfifo_t tx_fifo; /* TX FIFO */
|
|
|
- rkfifo_t rx_fifo; /* RX FIFO */
|
|
|
- volatile uint8_t dma_busy; /* DMA发送忙标志 */
|
|
|
-};
|
|
|
-
|
|
|
-struct _uart_ops {
|
|
|
- int (*init)(struct _uart_config *config, uint32_t baudrate);
|
|
|
- uint32_t (*read)(struct _uart_config *config, void *data, uint32_t len);
|
|
|
- uint32_t (*write)(struct _uart_config *config, const void *data, uint32_t len);
|
|
|
-};
|
|
|
-
|
|
|
-struct _uart_device {
|
|
|
- struct _uart_config *config;
|
|
|
- struct _uart_ops *ops;
|
|
|
-};
|
|
|
|
|
|
/* ========== 辅助函数:获取DMA完成标志指针 ========== */
|
|
|
static bool* _get_dma_done_flag(UART_Type *uart_base)
|
|
|
@@ -131,11 +61,11 @@ static void _uart_clock_enable(UART_Type *uart_base)
|
|
|
static void _dma_clock_enable(DMA_Type *dma_base)
|
|
|
{
|
|
|
/* HDMA 时钟来源于系统总线时钟(AHB),已默认使能 */
|
|
|
- (void)dma_base;
|
|
|
+ // clock_add_to_group(clock_hdma, 0);
|
|
|
}
|
|
|
|
|
|
/* ========== GPIO配置 ========== */
|
|
|
-static void _uart_gpio_config(UART_Type *uart_base)
|
|
|
+static void _uart_gpio_config(UART_Type *uart_base) // 根据实际引脚配置
|
|
|
{
|
|
|
if (uart_base == HPM_UART1) {
|
|
|
HPM_IOC->PAD[IOC_PAD_PA02].FUNC_CTL = IOC_PA02_FUNC_CTL_UART1_TXD;
|
|
|
@@ -171,9 +101,7 @@ static int _uart_config(struct _uart_config *config, uint32_t baudrate)
|
|
|
_uart_gpio_config(config->uart_base);
|
|
|
|
|
|
/* 获取UART时钟频率 */
|
|
|
- if (config->uart_base == HPM_UART0) {
|
|
|
- uart_clock_freq = clock_get_frequency(clock_uart0);
|
|
|
- } else if (config->uart_base == HPM_UART1) {
|
|
|
+ if (config->uart_base == HPM_UART1) {
|
|
|
uart_clock_freq = clock_get_frequency(clock_uart1);
|
|
|
} else if (config->uart_base == HPM_UART2) {
|
|
|
uart_clock_freq = clock_get_frequency(clock_uart2);
|
|
|
@@ -185,9 +113,7 @@ static int _uart_config(struct _uart_config *config, uint32_t baudrate)
|
|
|
uart_clock_freq = clock_get_frequency(clock_uart5);
|
|
|
} else if (config->uart_base == HPM_UART6) {
|
|
|
uart_clock_freq = clock_get_frequency(clock_uart6);
|
|
|
- } else if (config->uart_base == HPM_UART7) {
|
|
|
- uart_clock_freq = clock_get_frequency(clock_uart7);
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
/* 配置UART */
|
|
|
uart_default_config(config->uart_base, &uart_cfg);
|
|
|
@@ -223,7 +149,6 @@ static int _uart_dma_config(struct _uart_config *config)
|
|
|
DMA_SOC_CHN_TO_DMAMUX_CHN(config->dma_base, config->dma_channel),
|
|
|
config->dma_request,
|
|
|
true);
|
|
|
-
|
|
|
/* 配置 TX 握手参数 */
|
|
|
dma_default_handshake_config(config->dma_base, &handshake_config);
|
|
|
handshake_config.ch_index = config->dma_channel;
|
|
|
@@ -252,7 +177,9 @@ static void _uart_nvic_config(struct _uart_config *config)
|
|
|
|
|
|
/* 使能DMA中断 */
|
|
|
if (config->dma_enable) {
|
|
|
+
|
|
|
intc_m_enable_irq_with_priority(config->dma_irq_num, 1);
|
|
|
+ printf("DMA interrupt enabled for channel %d\n", config->dma_channel);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -274,60 +201,32 @@ int _uart_init(struct _uart_config *config, uint32_t baudrate)
|
|
|
/* 配置中断 */
|
|
|
_uart_nvic_config(config);
|
|
|
|
|
|
- config->dma_busy = 0;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * @brief 获取串口发送是否忙碌
|
|
|
- */
|
|
|
-bool usart_tx_isbusy(struct _uart_config *config)
|
|
|
-{
|
|
|
- bool *dma_done_flag = _get_dma_done_flag(config->uart_base);
|
|
|
-
|
|
|
- if (dma_done_flag) {
|
|
|
- return !(*dma_done_flag);
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
-}
|
|
|
|
|
|
+uint8_t TX_BUFF[256]={'0','1','3'};
|
|
|
void open_usart_dma_tx(struct _uart_config *config, uint32_t len)
|
|
|
{
|
|
|
dma_handshake_config_t handshake_config;
|
|
|
- bool *dma_done_flag = _get_dma_done_flag(config->uart_base);
|
|
|
-
|
|
|
- /* 等待上次发送完成 */
|
|
|
- uint32_t timeout = 1000000;
|
|
|
- while (usart_tx_isbusy(config) && timeout--) {
|
|
|
- __asm("nop");
|
|
|
- }
|
|
|
-
|
|
|
- if (timeout == 0) {
|
|
|
- /* 超时处理,复位DMA */
|
|
|
- dma_abort_channel(config->dma_base, config->dma_channel);
|
|
|
- if (dma_done_flag) {
|
|
|
- *dma_done_flag = true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* 清除DMA完成标志 */
|
|
|
- if (dma_done_flag) {
|
|
|
- *dma_done_flag = false;
|
|
|
- }
|
|
|
-
|
|
|
+
|
|
|
/* 重新配置 TX 传输大小 */
|
|
|
dma_default_handshake_config(config->dma_base, &handshake_config);
|
|
|
- handshake_config.ch_index = config->dma_channel;
|
|
|
- handshake_config.dst = (uint32_t)&config->uart_base->THR;
|
|
|
+ handshake_config.ch_index = config->dma_channel;
|
|
|
+ handshake_config.dst = (uint32_t)&(config->uart_base->THR);
|
|
|
handshake_config.dst_fixed = true;
|
|
|
- handshake_config.src = core_local_mem_to_sys_address(0, (uint32_t)config->dma_tx_buff);
|
|
|
+ handshake_config.src = core_local_mem_to_sys_address(0,(uint32_t)config->dma_tx_buff);
|
|
|
handshake_config.src_fixed = false;
|
|
|
handshake_config.data_width = DMA_TRANSFER_WIDTH_BYTE;
|
|
|
handshake_config.size_in_byte = len;
|
|
|
|
|
|
- dma_setup_handshake(config->dma_base, &handshake_config, true);
|
|
|
+ hpm_stat_t stat = dma_setup_handshake(config->dma_base, &handshake_config, true);
|
|
|
+ if(stat != status_success)
|
|
|
+ {
|
|
|
+ printf("uart dma tx config error\r\n");
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/* ========== UART发送数据(DMA方式) ========== */
|
|
|
@@ -341,16 +240,11 @@ static uint32_t uart_tx_data(struct _uart_config *config, const void *data, uint
|
|
|
ret = rkfifo_in(&config->tx_fifo, data, len);
|
|
|
|
|
|
if (config->dma_tx_buff != NULL && config->dma_enable) {
|
|
|
- /* DMA方式发送 */
|
|
|
- if (!config->dma_busy) {
|
|
|
- /* DMA空闲,立即发送 */
|
|
|
- uint32_t count = rkfifo_out(&config->tx_fifo,
|
|
|
- config->dma_tx_buff,
|
|
|
- config->dma_tx_buff_size);
|
|
|
- if (count > 0) {
|
|
|
- open_usart_dma_tx(config, count);
|
|
|
- config->dma_busy = 1;
|
|
|
- }
|
|
|
+
|
|
|
+ uint32_t count = rkfifo_out(&config->tx_fifo, config->dma_tx_buff, config->dma_tx_buff_size);
|
|
|
+ if (count > 0) {
|
|
|
+ open_usart_dma_tx(config, count);
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -393,16 +287,8 @@ void uart_isr_callback(struct _uart_config *config)
|
|
|
|
|
|
/* ========== DMA发送完成中断处理 ========== */
|
|
|
void uart_tx_dma_isr_callback(struct _uart_config *config)
|
|
|
-{
|
|
|
- bool *dma_done_flag = _get_dma_done_flag(config->uart_base);
|
|
|
-
|
|
|
- /* 设置DMA完成标志 */
|
|
|
- if (dma_done_flag) {
|
|
|
- *dma_done_flag = true;
|
|
|
- }
|
|
|
-
|
|
|
- config->dma_busy = 0;
|
|
|
-
|
|
|
+{
|
|
|
+
|
|
|
rkfifo_t *tx_fifo = &config->tx_fifo;
|
|
|
uint8_t *dma_buff = config->dma_tx_buff;
|
|
|
uint32_t dma_buff_size = config->dma_tx_buff_size;
|
|
|
@@ -410,29 +296,29 @@ void uart_tx_dma_isr_callback(struct _uart_config *config)
|
|
|
|
|
|
if (count > 0) {
|
|
|
open_usart_dma_tx(config, count);
|
|
|
- config->dma_busy = 1;
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* ========== UART1 配置 ========== */
|
|
|
#ifdef DRV_USING_UART1
|
|
|
-
|
|
|
-static uint8_t u1_rx_fifo_buff[UART_RX_FIFO_BUFFER_LEN];
|
|
|
-static uint8_t u1_tx_fifo_buff[UART_TX_FIFO_BUFFER_LEN];
|
|
|
-static uint8_t u1_dma_tx_buff[UART_TX_DMA_BUFFER_LEN];
|
|
|
+// ATTR_PLACE_AT_NONCACHEABLE这个一定不要忘记加
|
|
|
+static ATTR_PLACE_AT_NONCACHEABLE uint8_t u1_rx_fifo_buff[UART1_RX_FIFO_BUFFER_LEN];
|
|
|
+static ATTR_PLACE_AT_NONCACHEABLE uint8_t u1_tx_fifo_buff[UART1_TX_FIFO_BUFFER_LEN];
|
|
|
+static ATTR_PLACE_AT_NONCACHEABLE uint8_t u1_dma_tx_buff[UART1_TX_DMA_BUFFER_LEN];
|
|
|
|
|
|
struct _uart_config _u1_config = {
|
|
|
- .uart_base = HPM_UART1, /* 修正:应该是UART1 */
|
|
|
- .uart_irq_mask = uart_intr_rx_rdy | uart_intr_rx_timeout, /* 添加中断掩码 */
|
|
|
- .uart_irq_num = IRQn_UART1, /* 修正:IRQn_UART1 */
|
|
|
+ .uart_base = HPM_UART1,
|
|
|
+ .uart_irq_mask = uart_intr_rx_data_avail_or_timeout, /* 添加中断掩码 */
|
|
|
+ .uart_irq_num = IRQn_UART1,
|
|
|
|
|
|
/* DMA配置 */
|
|
|
- .dma_base = HPM_DMA0,
|
|
|
- .dma_mux_base = HPM_DMAMUX0,
|
|
|
- .dma_enable = 1, /* 修正拼写 */
|
|
|
+ .dma_base = HPM_HDMA,
|
|
|
+ .dma_mux_base = HPM_DMAMUX,
|
|
|
+ .dma_enable = 1,
|
|
|
.dma_channel = 0,
|
|
|
- .dma_irq_num = IRQn_DMA0_CH0,
|
|
|
- .dma_request = DMA_REQUEST_UART1_TX, /* 修正:UART1_TX */
|
|
|
+ .dma_irq_num = IRQn_HDMA,
|
|
|
+ .dma_request = HPM_DMA_SRC_UART1_TX,
|
|
|
|
|
|
/* FIFO缓冲区 */
|
|
|
.tx_fifo_buff = u1_tx_fifo_buff,
|
|
|
@@ -450,7 +336,7 @@ static uint32_t u1_write_data(const void *data, uint32_t len)
|
|
|
return uart_tx_data(&_u1_config, data, len);
|
|
|
}
|
|
|
|
|
|
-static uint32_t u1_read_data(void *data, uint32_t len)
|
|
|
+static uint32_t u1_read_data( void *data, uint32_t len)
|
|
|
{
|
|
|
return uart_rx_data(&_u1_config, data, len);
|
|
|
}
|
|
|
@@ -470,20 +356,81 @@ static struct _uart_device uart1 = {
|
|
|
.config = &_u1_config,
|
|
|
.ops = &_u1_ops,
|
|
|
};
|
|
|
-
|
|
|
/* UART1中断处理函数 */
|
|
|
-void uart1_irq_handler(void)
|
|
|
+SDK_DECLARE_EXT_ISR_M(IRQn_UART1, uart1_isr)
|
|
|
+void uart1_isr(void)
|
|
|
+{
|
|
|
+ uart_isr_callback(&_u1_config);
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef DRV_USING_UART4
|
|
|
+// ATTR_PLACE_AT_NONCACHEABLE这个一定不要忘记加
|
|
|
+static ATTR_PLACE_AT_NONCACHEABLE uint8_t u4_rx_fifo_buff[UART4_RX_FIFO_BUFFER_LEN];
|
|
|
+static ATTR_PLACE_AT_NONCACHEABLE uint8_t u4_tx_fifo_buff[UART4_TX_FIFO_BUFFER_LEN];
|
|
|
+static ATTR_PLACE_AT_NONCACHEABLE uint8_t u4_dma_tx_buff[UART4_TX_DMA_BUFFER_LEN];
|
|
|
+
|
|
|
+struct _uart_config _u4_config = {
|
|
|
+ .uart_base = HPM_UART4,
|
|
|
+ .uart_irq_mask = uart_intr_rx_data_avail_or_timeout, /* 添加中断掩码 */
|
|
|
+ .uart_irq_num = IRQn_UART4,
|
|
|
+
|
|
|
+ /* DMA配置 */
|
|
|
+ .dma_base = HPM_HDMA,
|
|
|
+ .dma_mux_base = HPM_DMAMUX,
|
|
|
+ .dma_enable = 1,
|
|
|
+ .dma_channel = 0,
|
|
|
+ .dma_irq_num = IRQn_HDMA,
|
|
|
+ .dma_request = HPM_DMA_SRC_UART4_TX,
|
|
|
+
|
|
|
+ /* FIFO缓冲区 */
|
|
|
+ .tx_fifo_buff = u4_tx_fifo_buff,
|
|
|
+ .tx_fifo_buff_size = sizeof(u4_tx_fifo_buff),
|
|
|
+ .rx_fifo_buff = u4_rx_fifo_buff,
|
|
|
+ .rx_fifo_buff_size = sizeof(u4_rx_fifo_buff),
|
|
|
+
|
|
|
+ /* DMA缓冲区 */
|
|
|
+ .dma_tx_buff = u4_dma_tx_buff,
|
|
|
+ .dma_tx_buff_size = sizeof(u4_dma_tx_buff),
|
|
|
+};
|
|
|
+
|
|
|
+static uint32_t u4_write_data(const void *data, uint32_t len)
|
|
|
+{
|
|
|
+ return uart_tx_data(&_u4_config, data, len);
|
|
|
+}
|
|
|
+
|
|
|
+static uint32_t u4_read_data( void *data, uint32_t len)
|
|
|
{
|
|
|
- uart_isr_callback(&_u1_config);
|
|
|
+ return uart_rx_data(&_u4_config, data, len);
|
|
|
}
|
|
|
|
|
|
-/* DMA0通道0中断处理函数 */
|
|
|
-void dma0_ch0_irq_handler(void)
|
|
|
+static int u4_init(uint32_t baudrate)
|
|
|
+{
|
|
|
+ return _uart_init(&_u4_config, baudrate);
|
|
|
+}
|
|
|
+
|
|
|
+static struct _uart_ops _u4_ops = {
|
|
|
+ .init = u4_init,
|
|
|
+ .read = u4_read_data,
|
|
|
+ .write = u4_write_data,
|
|
|
+};
|
|
|
+
|
|
|
+static struct _uart_device uart4 = {
|
|
|
+ .config = &_u4_config,
|
|
|
+ .ops = &_u4_ops,
|
|
|
+};
|
|
|
+
|
|
|
+/* UART4中断处理函数 */
|
|
|
+SDK_DECLARE_EXT_ISR_M(IRQn_UART4, uart4_isr)
|
|
|
+void uart4_isr(void)
|
|
|
{
|
|
|
- uart_tx_dma_isr_callback(&_u1_config);
|
|
|
+ uart_isr_callback(&_u4_config);
|
|
|
}
|
|
|
|
|
|
-#endif /* DRV_USING_UART1 */
|
|
|
+
|
|
|
+
|
|
|
+#endif /* DRV_USING_UART4 */
|
|
|
|
|
|
/* ========== UART查找函数 ========== */
|
|
|
struct _uart_device *uart_find(const char *name)
|
|
|
@@ -517,4 +464,454 @@ struct _uart_device *uart_find(const char *name)
|
|
|
}
|
|
|
|
|
|
return uart;
|
|
|
-}
|
|
|
+}
|
|
|
+
|
|
|
+// 通用串口驱动测试例程 20260323 pass
|
|
|
+#ifdef UART_DRV_TEST
|
|
|
+
|
|
|
+/* uart_test.c
|
|
|
+ * UART驱动测试例程
|
|
|
+ * 测试功能:发送测试、接收测试、回环测试、DMA传输测试
|
|
|
+ */
|
|
|
+
|
|
|
+#include "board.h"
|
|
|
+#include "my_board.h"
|
|
|
+#include "drv_usart.h"
|
|
|
+#include <stdio.h>
|
|
|
+#include <string.h>
|
|
|
+
|
|
|
+/* ========== 测试配置 ========== */
|
|
|
+#define TEST_UART_NAME "uart3" /* 测试的UART名称 */
|
|
|
+#define TEST_BAUDRATE 115200 /* 波特率 */
|
|
|
+#define TEST_BUFFER_SIZE 256 /* 测试缓冲区大小 */
|
|
|
+#define TEST_LOOP_COUNT 10 /* 回环测试次数 */
|
|
|
+
|
|
|
+/* 测试标志 */
|
|
|
+static uint32_t test_pass_count = 0;
|
|
|
+static uint32_t test_fail_count = 0;
|
|
|
+
|
|
|
+/* ========== 辅助函数 ========== */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 打印测试结果
|
|
|
+ */
|
|
|
+static void print_test_result(const char *test_name, bool passed)
|
|
|
+{
|
|
|
+ if (passed) {
|
|
|
+ printf("[PASS] %s\n", test_name);
|
|
|
+ test_pass_count++;
|
|
|
+ } else {
|
|
|
+ printf("[FAIL] %s\n", test_name);
|
|
|
+ test_fail_count++;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 打印测试汇总
|
|
|
+ */
|
|
|
+static void print_test_summary(void)
|
|
|
+{
|
|
|
+ printf("\n========== Test Summary ==========\n");
|
|
|
+ printf("Total Tests: %d\n", test_pass_count + test_fail_count);
|
|
|
+ printf("Passed: %d\n", test_pass_count);
|
|
|
+ printf("Failed: %d\n", test_fail_count);
|
|
|
+ printf("==================================\n");
|
|
|
+
|
|
|
+ if (test_fail_count == 0) {
|
|
|
+ printf("All tests PASSED!\n");
|
|
|
+ } else {
|
|
|
+ printf("Some tests FAILED!\n");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 延迟函数(毫秒)
|
|
|
+ */
|
|
|
+static void delay_ms(uint32_t ms)
|
|
|
+{
|
|
|
+ board_delay_ms(ms);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 生成测试数据
|
|
|
+ */
|
|
|
+static void generate_test_data(uint8_t *buffer, uint32_t len, uint8_t pattern)
|
|
|
+{
|
|
|
+ for (uint32_t i = 0; i < len; i++) {
|
|
|
+ buffer[i] = pattern+i;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 验证数据是否正确
|
|
|
+ */
|
|
|
+static bool verify_test_data(uint8_t *buffer, uint32_t len, uint8_t pattern)
|
|
|
+{
|
|
|
+ for (uint32_t i = 0; i < len; i++) {
|
|
|
+ if (buffer[i] != (pattern + i)) {
|
|
|
+ printf("Data mismatch at pos %d: expected 0x%02X, got 0x%02X\n",
|
|
|
+ i, pattern + i, buffer[i]);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+/* ========== 测试用例 ========== */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试1:UART初始化
|
|
|
+ */
|
|
|
+static void test_uart_init(struct _uart_device *uart_dev)
|
|
|
+{
|
|
|
+ printf("\n--- Test 1: UART Init ---\n");
|
|
|
+
|
|
|
+ if (uart_dev == NULL) {
|
|
|
+ printf("UART device not found!\n");
|
|
|
+ print_test_result("UART Init", false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ int ret = uart_dev->ops->init( TEST_BAUDRATE);
|
|
|
+ if (ret == 0) {
|
|
|
+ printf("UART initialized successfully at %d baud\n", TEST_BAUDRATE);
|
|
|
+ print_test_result("UART Init", true);
|
|
|
+ } else {
|
|
|
+ printf("UART init failed with code: %d\n", ret);
|
|
|
+ print_test_result("UART Init", false);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试2:单字节发送和接收(回环测试)
|
|
|
+ * 需要将TX和RX引脚短接
|
|
|
+ */
|
|
|
+static void test_single_byte_loopback(struct _uart_device *uart_dev)
|
|
|
+{
|
|
|
+ printf("\n--- Test 2: Single Byte Loopback ---\n");
|
|
|
+ printf("NOTE: Please short TX and RX pins for this test!\n");
|
|
|
+
|
|
|
+ delay_ms(100); /* 等待用户准备 */
|
|
|
+
|
|
|
+ uint8_t test_byte = 0x5A;
|
|
|
+ uint8_t recv_byte = 0;
|
|
|
+ uint32_t timeout = 10000;
|
|
|
+
|
|
|
+ /* 发送数据 */
|
|
|
+ uint32_t sent = uart_dev->ops->write( &test_byte, 1);
|
|
|
+ if (sent != 1) {
|
|
|
+ printf("Failed to send byte\n");
|
|
|
+ print_test_result("Single Byte Loopback", false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ printf("Sent: 0x%02X\n", test_byte);
|
|
|
+
|
|
|
+ /* 等待接收 */
|
|
|
+ while (timeout--) {
|
|
|
+ uint32_t received = uart_dev->ops->read( &recv_byte, 1);
|
|
|
+ if (received == 1) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ delay_ms(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (timeout == 0) {
|
|
|
+ printf("Timeout waiting for data\n");
|
|
|
+ print_test_result("Single Byte Loopback", false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("Received: 0x%02X\n", recv_byte);
|
|
|
+
|
|
|
+ if (test_byte == recv_byte) {
|
|
|
+ print_test_result("Single Byte Loopback", true);
|
|
|
+ } else {
|
|
|
+ printf("Data mismatch!\n");
|
|
|
+ print_test_result("Single Byte Loopback", false);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试3:多字节发送和接收(回环测试)
|
|
|
+ */
|
|
|
+static void test_multi_byte_loopback(struct _uart_device *uart_dev)
|
|
|
+{
|
|
|
+ printf("\n--- Test 3: Multi-Byte Loopback ---\n");
|
|
|
+
|
|
|
+ uint8_t tx_buffer[64];
|
|
|
+ uint8_t rx_buffer[64];
|
|
|
+ uint32_t test_len = 64;
|
|
|
+
|
|
|
+ /* 生成测试数据 */
|
|
|
+ generate_test_data(tx_buffer, test_len, 0x40);
|
|
|
+ memset(rx_buffer, 0, test_len);
|
|
|
+
|
|
|
+ /* 发送数据 */
|
|
|
+ uint32_t sent = uart_dev->ops->write( tx_buffer, test_len);
|
|
|
+ if (sent != test_len) {
|
|
|
+ printf("Failed to send data: sent %d, expected %d\n", sent, test_len);
|
|
|
+ print_test_result("Multi-Byte Loopback", false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ printf("Sent %d bytes\n", sent);
|
|
|
+
|
|
|
+ /* 等待接收完成 */
|
|
|
+ uint32_t total_received = 0;
|
|
|
+ uint32_t timeout = 100000;
|
|
|
+
|
|
|
+ while (total_received < test_len && timeout--) {
|
|
|
+ uint32_t received = uart_dev->ops->read(
|
|
|
+ &rx_buffer[total_received],
|
|
|
+ test_len - total_received);
|
|
|
+ if (received > 0) {
|
|
|
+ total_received += received;
|
|
|
+ }
|
|
|
+ delay_ms(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (timeout == 0) {
|
|
|
+ printf("Timeout: received %d/%d bytes\n", total_received, test_len);
|
|
|
+ print_test_result("Multi-Byte Loopback", false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("Received %d bytes\n", total_received);
|
|
|
+
|
|
|
+ /* 验证数据 */
|
|
|
+ if (verify_test_data(rx_buffer, test_len, 0x40)) {
|
|
|
+ print_test_result("Multi-Byte Loopback", true);
|
|
|
+ } else {
|
|
|
+ print_test_result("Multi-Byte Loopback", false);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试4:DMA发送测试
|
|
|
+ */
|
|
|
+static void test_dma_transmit(struct _uart_device *uart_dev)
|
|
|
+{
|
|
|
+ printf("\n--- Test 4: DMA Transmit Test ---\n");
|
|
|
+
|
|
|
+ /* 检查是否支持DMA */
|
|
|
+ if (!uart_dev->config->dma_enable || uart_dev->config->dma_tx_buff == NULL) {
|
|
|
+ printf("DMA not enabled for this UART\n");
|
|
|
+ print_test_result("DMA Transmit", false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ uint8_t tx_buffer[256];
|
|
|
+ uint32_t test_len = 256;
|
|
|
+
|
|
|
+ generate_test_data(tx_buffer, test_len, 0x30);
|
|
|
+ tx_buffer[255] = 0;
|
|
|
+ //printf("%s\r\n", tx_buffer);
|
|
|
+ /* 通过DMA发送 */
|
|
|
+ // uart_send_data(HPM_UART3, tx_buffer, 128);
|
|
|
+ uint32_t sent = uart_dev->ops->write( tx_buffer, test_len);
|
|
|
+
|
|
|
+ if (sent != test_len) {
|
|
|
+ printf("DMA send failed: sent %d, expected %d\n", sent, test_len);
|
|
|
+ print_test_result("DMA Transmit", false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("DMA sent %d bytes\n", sent);
|
|
|
+
|
|
|
+
|
|
|
+ printf("DMA transfer completed\n");
|
|
|
+ print_test_result("DMA Transmit", true);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试5:压力测试 - 连续发送接收
|
|
|
+ */
|
|
|
+static void test_stress_loopback(struct _uart_device *uart_dev)
|
|
|
+{
|
|
|
+ printf("\n--- Test 5: Stress Test (Continuous Loopback) ---\n");
|
|
|
+
|
|
|
+ uint8_t tx_buffer[32];
|
|
|
+ uint8_t rx_buffer[32];
|
|
|
+ uint32_t total_tests = TEST_LOOP_COUNT;
|
|
|
+ uint32_t pass_tests = 0;
|
|
|
+
|
|
|
+ for (uint32_t i = 0; i < total_tests; i++) {
|
|
|
+ uint8_t pattern = (uint8_t)(0x10 + i);
|
|
|
+ uint32_t test_len = 16 + (i % 16); /* 可变长度测试 */
|
|
|
+
|
|
|
+ generate_test_data(tx_buffer, test_len, pattern);
|
|
|
+ memset(rx_buffer, 0, test_len);
|
|
|
+
|
|
|
+ /* 发送 */
|
|
|
+ uint32_t sent = uart_dev->ops->write( tx_buffer, test_len);
|
|
|
+ if (sent != test_len) {
|
|
|
+ printf("Test %d: Send failed\n", i);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 接收 */
|
|
|
+ uint32_t total_received = 0;
|
|
|
+ uint32_t timeout = 10000;
|
|
|
+
|
|
|
+ while (total_received < test_len && timeout--) {
|
|
|
+ uint32_t received = uart_dev->ops->read(
|
|
|
+ &rx_buffer[total_received],
|
|
|
+ test_len - total_received);
|
|
|
+ if (received > 0) {
|
|
|
+ total_received += received;
|
|
|
+ }
|
|
|
+ delay_ms(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (total_received != test_len) {
|
|
|
+ printf("Test %d: Received %d/%d bytes\n", i, total_received, test_len);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 验证 */
|
|
|
+ if (verify_test_data(rx_buffer, test_len, pattern)) {
|
|
|
+ pass_tests++;
|
|
|
+ } else {
|
|
|
+ printf("Test %d: Data verification failed\n", i);
|
|
|
+ }
|
|
|
+
|
|
|
+ delay_ms(10); /* 测试间隔 */
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("Stress test: %d/%d passed\n", pass_tests, total_tests);
|
|
|
+ print_test_result("Stress Test", (pass_tests == total_tests));
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试6:波特率准确性测试
|
|
|
+ */
|
|
|
+static void test_baudrate_accuracy(struct _uart_device *uart_dev)
|
|
|
+{
|
|
|
+ printf("\n--- Test 6: Baudrate Accuracy Test ---\n");
|
|
|
+
|
|
|
+ /* 发送一串特定字符,在接收端验证 */
|
|
|
+ const char *test_string = "Hello UART! 1234567890\r\n";
|
|
|
+ uint32_t test_len = strlen(test_string);
|
|
|
+ char rx_buffer[128];
|
|
|
+
|
|
|
+ printf("Sending: %s", test_string);
|
|
|
+
|
|
|
+ uint32_t sent = uart_dev->ops->write(test_string, test_len);
|
|
|
+ if (sent != test_len) {
|
|
|
+ print_test_result("Baudrate Accuracy", false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 等待接收 */
|
|
|
+ uint32_t total_received = 0;
|
|
|
+ uint32_t timeout = 50000;
|
|
|
+
|
|
|
+ while (total_received < test_len && timeout--) {
|
|
|
+ uint32_t received = uart_dev->ops->read(
|
|
|
+ &rx_buffer[total_received],
|
|
|
+ test_len - total_received);
|
|
|
+ if (received > 0) {
|
|
|
+ total_received += received;
|
|
|
+ }
|
|
|
+ delay_ms(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (total_received != test_len) {
|
|
|
+ printf("Received %d/%d bytes\n", total_received, test_len);
|
|
|
+ print_test_result("Baudrate Accuracy", false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ rx_buffer[total_received] = '\0';
|
|
|
+ printf("Received: %s", rx_buffer);
|
|
|
+
|
|
|
+ if (memcmp(test_string, rx_buffer, test_len) == 0) {
|
|
|
+ print_test_result("Baudrate Accuracy", true);
|
|
|
+ } else {
|
|
|
+ printf("Data mismatch!\n");
|
|
|
+ print_test_result("Baudrate Accuracy", false);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* ========== 主测试函数 ========== */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief UART测试主函数
|
|
|
+ * @param test_mode 测试模式:
|
|
|
+ * 0 - 完整测试(需要TX/RX短接)
|
|
|
+ * 1 - 仅发送测试(不需要短接)
|
|
|
+ */
|
|
|
+int uart_test_main(int test_mode)
|
|
|
+{
|
|
|
+ struct _uart_device *uart_dev = NULL;
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+ printf("========================================\n");
|
|
|
+ printf(" UART Driver Test Suite\n");
|
|
|
+ printf("========================================\n");
|
|
|
+ printf("Testing UART: %s\n", TEST_UART_NAME);
|
|
|
+ printf("Baudrate: %d\n", TEST_BAUDRATE);
|
|
|
+ printf("Test Mode: %s\n", test_mode == 0 ? "Full (Loopback)" : "Transmit Only");
|
|
|
+ printf("========================================\n");
|
|
|
+
|
|
|
+ /* 查找UART设备 */
|
|
|
+ uart_dev = uart_find(TEST_UART_NAME);
|
|
|
+ if (uart_dev == NULL) {
|
|
|
+ printf("Error: UART device '%s' not found!\n", TEST_UART_NAME);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ printf("UART device found\n");
|
|
|
+
|
|
|
+ /* 重置测试计数器 */
|
|
|
+ test_pass_count = 0;
|
|
|
+ test_fail_count = 0;
|
|
|
+
|
|
|
+ /* 执行测试 */
|
|
|
+ test_uart_init(uart_dev);
|
|
|
+
|
|
|
+ if (test_mode == 0) {
|
|
|
+ /* 完整测试模式 - 需要TX/RX短接 */
|
|
|
+ test_single_byte_loopback(uart_dev);
|
|
|
+ test_multi_byte_loopback(uart_dev);
|
|
|
+ test_stress_loopback(uart_dev);
|
|
|
+ test_baudrate_accuracy(uart_dev);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* DMA测试(无论是否回环都可以测试) */
|
|
|
+ test_dma_transmit(uart_dev);
|
|
|
+
|
|
|
+ /* 打印测试结果 */
|
|
|
+ print_test_summary();
|
|
|
+
|
|
|
+ return (test_fail_count == 0) ? 0 : -1;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 简单的打印测试(用于验证基本功能)
|
|
|
+ */
|
|
|
+int uart_simple_print_test(void)
|
|
|
+{
|
|
|
+ struct _uart_device *uart_dev = NULL;
|
|
|
+ const char *message = "Hello from UART test!\r\n";
|
|
|
+
|
|
|
+ uart_dev = uart_find(TEST_UART_NAME);
|
|
|
+ if (uart_dev == NULL) {
|
|
|
+ printf("UART device not found!\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 初始化UART */
|
|
|
+ if (uart_dev->ops->init( TEST_BAUDRATE) != 0) {
|
|
|
+ printf("UART init failed!\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("UART initialized, sending test message...\n");
|
|
|
+
|
|
|
+ /* 发送测试消息 */
|
|
|
+ uint32_t sent = uart_dev->ops->write(message, strlen(message));
|
|
|
+ printf("Sent %d bytes: %s", sent, message);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#endif
|