确认slip用的中断接收
author孙春阳 <snickersun@163.com>
Sat, 11 Oct 2025 08:52:08 +0000 (16:52 +0800)
committer孙春阳 <snickersun@163.com>
Sat, 11 Oct 2025 08:52:08 +0000 (16:52 +0800)
ppp也用的中断接收

12 files changed:
code/sdk/build/config/target_config/brandy/config.py
code/sdk/drivers/chips/brandy/porting/uart/uart_porting.c
code/sdk/drivers/drivers/driver/uart/uart.c
code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/arch/sio.c
code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/test/slip_test.c
code/sdk/zhihui/ppp/example/ppp_at_cmd.c
code/sdk/zhihui/ppp/include/ppp_api.h
code/sdk/zhihui/ppp/include/ppp_config.h
code/sdk/zhihui/ppp/include/ppp_serial.h
code/sdk/zhihui/ppp/src/ppp_api.c
code/sdk/zhihui/ppp/src/ppp_lwip_thread.c
code/sdk/zhihui/ppp/src/ppp_serial.c

index 5e05a96..42cba78 100644 (file)
@@ -1237,6 +1237,7 @@ target = {
             'BOARD_LEINIAO',
             # cat1 相关配置
             'FT_SINGLE_UART',
+            'SUPPORT_CAT1_SERVICE',
             
             'CONFIG_EFUSE_READ_TO_RAM',
              'CUSTOM_UTILS',
@@ -1449,8 +1450,12 @@ target = {
             'AUDIO_SMARTPA_AW88082',
             'LCD_JD9885',
             'SUPPORT_LEINIAO',
-            'SKIP_LN_PROTOCOL_TEST',
+            #跳过雷鸟协议,方便做ppp测试
+            # 'SKIP_LN_PROTOCOL_TEST',
+            #ppp polling 读取串口 , 需要设置DMA读取才能提速 ,与interrupt只能开启一个
             # 'SUPPORT_PPP_SERVICE_POLLING',
+            # 'CONFIG_UART_SUPPORT_DMA',
+            # ppp interrupt 读取串口 与polling只能开启一个
             'SUPPORT_PPP_SERVICE_INTERRUPT',
         ],
         #添加自定义应用
index b7d3397..de05aee 100644 (file)
@@ -172,7 +172,7 @@ static uart_config_t g_uart_config[UART_BUS_MAX_NUMBER] = {
     /** UART_BUS_0, which is used to at cmd and debug print in wstp version,
      * and which is used to testustie and debug print in testsuite version
      */
-    #if defined(SUPPORT_CAT1_SERVICE)  || defined(SUPPORT_PPP_SERVICE_POLLING)
+    #if defined(SUPPORT_PPP_SERVICE_POLLING)
     {
         {
             .tx_pin = PIN_NONE,
@@ -202,7 +202,7 @@ static uart_config_t g_uart_config[UART_BUS_MAX_NUMBER] = {
         NULL, //uart_mutex
         false, //support_mutex
     },
-    #elif defined(SUPPORT_PPP_SERVICE_INTERRUPT)
+    #elif defined(SUPPORT_PPP_SERVICE_INTERRUPT) || defined(SUPPORT_CAT1_SERVICE) 
     {
         {
             .tx_pin = S_MGPIO19,
@@ -220,7 +220,7 @@ static uart_config_t g_uart_config[UART_BUS_MAX_NUMBER] = {
         (osal_irq_handler)irq_uart0_handler,
         NULL,
         {
-            .baud_rate = CUSTOM_UART_RATE,
+            .baud_rate = 921600,
             .data_bits = UART_DATA_BIT_8,
             .parity = UART_PARITY_NONE,
             .stop_bits = UART_STOP_BIT_1,
index 1854436..170486a 100644 (file)
@@ -636,11 +636,11 @@ int32_t uapi_uart_read_by_dma(uart_bus_t bus, const void *buffer, uint32_t lengt
     }
 
     if ((buffer == NULL) || (length == 0)) {
-        return -1;
+        return -2;
     }
 
     if (length % bit(dma_cfg->src_width) != 0) {
-        return -1;
+        return -3;
     }
 
     dma_ch_user_peripheral_config_t user_cfg = {0};
@@ -648,36 +648,39 @@ int32_t uapi_uart_read_by_dma(uart_bus_t bus, const void *buffer, uint32_t lengt
 
     int32_t ret = uart_read_by_dma_config(bus, buffer, length, dma_cfg, &user_cfg);
     if (ret != ERRCODE_SUCC || user_cfg.src_handshaking == HAL_DMA_HANDSHAKING_MAX_NUM) {
-        return -1;
+        return ret;
     }
 
-    if (uapi_dma_configure_peripheral_transfer_single(&user_cfg, &dma_ch,
-        uart_dma_isr, (uintptr_t)NULL) != ERRCODE_SUCC) {
-        return -1;
+    ret = uapi_dma_configure_peripheral_transfer_single(&user_cfg, &dma_ch,
+        uart_dma_isr, (uintptr_t)NULL) ;
+    if (ret != ERRCODE_SUCC) {
+        return ret;
     }
 
     g_dma_trans[bus].channel = dma_ch + 1;
     g_dma_trans[bus].trans_succ = false;
 
     uapi_pm_add_sleep_veto(PM_ID_UART_DMA);
-    if (uapi_dma_start_transfer(dma_ch) != ERRCODE_SUCC) {
+    ret = uapi_dma_start_transfer(dma_ch);
+    if (ret != ERRCODE_SUCC) {
         uapi_pm_remove_sleep_veto(PM_ID_UART_DMA);
         g_dma_trans[bus].channel = 0;
-        return -1;
+        return ret;
     }
 
-    if (osal_sem_down_timeout(&(g_dma_trans[bus].dma_sem), UART_DMA_TRANSFER_TIMEOUT_MS) != OSAL_SUCCESS) {
+    ret = osal_sem_down_timeout(&(g_dma_trans[bus].dma_sem), UART_DMA_TRANSFER_TIMEOUT_MS);
+    if (ret != OSAL_SUCCESS) {
         uapi_dma_end_transfer(dma_ch);
         uapi_pm_remove_sleep_veto(PM_ID_UART_DMA);
         g_dma_trans[bus].channel = 0;
-        return -1;
+        return ret;
     }
 
     uapi_pm_remove_sleep_veto(PM_ID_UART_DMA);
     g_dma_trans[bus].channel = 0;
 
     if (!g_dma_trans[bus].trans_succ) {
-        return -1;
+        return -8;
     }
 
     return (int32_t)uapi_dma_get_block_ts(dma_ch);
index 5505950..dc23fc6 100644 (file)
@@ -91,8 +91,9 @@ static errcode_t sio_uart_init(void)
 
     printf(" %s %d\n", __FUNCTION__, __LINE__);
     /* Initialize UART */
-    ret = uapi_uart_init(SIO_UART_BUS, (const void*)&g_sio_uart_pin_config, 
-                         (const void*)&g_sio_uart_attr, NULL, (void*)&g_sio_uart_buffer_config);
+    // ret = uapi_uart_init(SIO_UART_BUS, (const void*)&g_sio_uart_pin_config, 
+                        //  (const void*)&g_sio_uart_attr, NULL, (void*)&g_sio_uart_buffer_config);
+    ret = uapi_uart_set_attr(SIO_UART_BUS, (const void*)&g_sio_uart_attr);
     if (ret != ERRCODE_SUCC) {
         return ret;
     }
index 31432c2..ba19351 100644 (file)
@@ -99,12 +99,33 @@ void slip_test_send(void)
         printf("Failed to allocate pbuf for test data\n");
     }
 }
+static void count_rx_bytes(uint16_t length)
+{
+    // INSERT_YOUR_CODE
+    // 打印接收到的数据量,每10秒打印一次
+    static uint32_t total_rx_bytes = 0;
+    static uint32_t last_print_time_ms = 0;
+
+    total_rx_bytes += length;
+
+    // 获取当前时间(使用tick或者ms级时钟,根据平台实现,这里假设有LOS_TickCountGet/LOS_MsoGetTickCount可用,单位ms)
+    uint32_t now_ms = LOS_TickCountGet(); // 使用你的平台API,或许是osKernelGetTickCount等
 
+    if (last_print_time_ms == 0) {
+        last_print_time_ms = now_ms;
+    }
+    if ((now_ms - last_print_time_ms) >= 10000) {
+        printf("[SLIP] Received %u bytes in last %u ms\n", total_rx_bytes, (now_ms - last_print_time_ms));
+        total_rx_bytes = 0;
+        last_print_time_ms = now_ms;
+    }
+}
 void uart_read_data_int_handler(const void *buffer, uint16_t length, bool error)
 {
     if (slipif_initialled == true)
     {
         slipif_received_bytes(&slip_netif,buffer,length);
+        count_rx_bytes(length);
     }
 }
 /**
index 1acaf94..f9d7995 100644 (file)
@@ -688,24 +688,6 @@ static errcode_t at_ppp_transparent(uint8_t *para, uint32_t paraLen)
     }
 }
 
-/* PPP智能flush测试指令 */
-static errcode_t at_ppp_flush(uint8_t *para, uint32_t paraLen)
-{
-    (void)para;
-    (void)paraLen;
-    
-    ppp_print_info("PPP FLUSH: Triggering periodic flush check...\n");
-    
-    errcode_t ret = ppp_test_smart_flush();
-    if (ret == ERRCODE_SUCC) {
-        ppp_print_info("PPP FLUSH: Periodic flush completed successfully\n");
-    } else {
-        ppp_print_err("PPP FLUSH: Periodic flush failed, error: %d\n", ret);
-    }
-    
-    return ret;
-}
-
 /* PPP环境初始化测试指令 */
 static errcode_t at_ppp_env_init(uint8_t *para, uint32_t paraLen)
 {
@@ -1024,7 +1006,7 @@ static errcode_t at_ppp_show_runtime(uint8_t *para, uint32_t paraLen)
 
     // 打印中断统计信息
     ppp_interrupt_print_stats();
-    
+
     return ERRCODE_SUCC;
 }
 
@@ -2517,7 +2499,6 @@ static const at_cmd_table_t g_ppp_cmd[] = {
     /* PPP串口测试指令 */
     { (char *)"AT^PPPSTATUS",       at_ppp_status, (char *)" " },
     { (char *)"AT^PPPTRANS",        at_ppp_transparent, (char *)"AT_COMMAND" },
-    { (char *)"AT^PPPFLUSH",        at_ppp_flush, (char *)" " },
     /* PPP模块化函数测试指令 */
     { (char *)"AT^PPPENVINIT",      at_ppp_env_init, (char *)" " },
     { (char *)"AT^PPPSTARTDIAL",    at_ppp_start_dial, (char *)" " },
index 3adabc7..69eee36 100644 (file)
@@ -111,11 +111,6 @@ errcode_t ppp_execute_at_command(const char *at_command,
                                      uint32_t timeout_ms);
 
 
-/**
- * @brief PPP智能flush测试
- * @return 错误码
- */
-errcode_t ppp_test_smart_flush(void);
 
 /**
  * @brief 检查4G电源是否已初始化
index e960eea..3ab6a1e 100644 (file)
@@ -50,11 +50,18 @@ extern "C" {
 #define PPP_KEEPALIVE_INTERVAL      30                  // 保活间隔(秒)
 
 /* PPP接收模式配置 */
-#ifndef PPP_USE_INTERRUPT_MODE
+#ifndef SUPPORT_PPP_SERVICE_POLLING
+#define PPP_USE_INTERRUPT_MODE      0                  // 1=中断模式(UART中断接收), 0=轮询模式(线程轮询)
+#elif defined(SUPPORT_PPP_SERVICE_INTERRUPT)
 #define PPP_USE_INTERRUPT_MODE      1                  // 1=中断模式(UART中断接收), 0=轮询模式(线程轮询)
 #endif
 //测试串口读取能力,注意不要注释掉,只用1和0 开启关闭即可。否则可能影响编译
+
+#if defined(SKIP_LN_PROTOCOL_TEST)
+#define PPP_DO_SERIAL_TEST          1                   // 1=进行串口读取能力测试, 0=不进行串口读取能力测试
+#else
 #define PPP_DO_SERIAL_TEST          0                   // 1=进行串口读取能力测试, 0=不进行串口读取能力测试
+#endif
 
 
 /* PPP性能优化配置 - 解决接收阻塞问题 */
@@ -75,6 +82,8 @@ extern "C" {
 
 /* 调试配置 */
 #define PPP_DEBUG_ENABLE            1                   // 启用调试输出
+// #define PPP_DEBUG_LEVEL             PPP_DEBUG_LEVEL_DEBUG // 默认只显示警告和错误 (1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)
+// #define PPP_DEBUG_LEVEL             PPP_DEBUG_LEVEL_INFO // 默认只显示警告和错误 (1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)
 #define PPP_DEBUG_LEVEL             PPP_DEBUG_LEVEL_WARN // 默认只显示警告和错误 (1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)
 
 /*
index 2d7f2b5..b0b393e 100644 (file)
@@ -126,28 +126,7 @@ uint32_t ppp_serial_available(void);
  */
 void ppp_serial_flush_rx(void);
 
-/**
- * @brief 强制发送缓冲区中的所有数据
- * @return 错误码
- */
-ppp_error_t ppp_serial_flush_tx(void);
-
-/**
- * @brief 清空发送缓冲区(丢弃数据)
- */
-void ppp_serial_flush_tx_discard(void);
-
-/**
- * @brief 获取发送缓冲区使用情况
- * @return 发送缓冲区中的数据量
- */
-uint32_t ppp_serial_tx_available(void);
-
-/**
- * @brief 定时flush检查函数(智能flush策略)
- * @return 错误码
- */
-ppp_error_t ppp_serial_periodic_flush(void);
+/* TX buffer removed - 发送改为直接UART写入,无需buffer和flush */
 
 /**
  * @brief 设置接收回调函数
index 731587f..b7e9a09 100644 (file)
@@ -1147,16 +1147,6 @@ errcode_t ppp_execute_at_command(const char *at_command,
 }
 
 
-
-/**
- * @brief PPP智能flush测试
- */
-errcode_t ppp_test_smart_flush(void)
-{
-    ppp_error_t ret = ppp_serial_periodic_flush();
-    return (ret == PPP_ERR_OK) ? ERRCODE_SUCC : ERRCODE_FAIL;
-}
-
 /**
  * @brief 获取PPP测试统计信息
  */
index 580b9a1..d9d786a 100644 (file)
@@ -345,8 +345,10 @@ static void ppp_lwip_receive_thread(void *arg)
     PPP_DEBUG_INFO("PPP receive thread started (ping-pong polling mode)");
 
     // 分配临时读取缓冲区(最大读取大小)
+    // ⚠️ 关键修复:使用 osal_kmalloc 在 RAM 中分配,DMA 不支持 PSRAM 地址!
+    // malloc() 可能分配在 PSRAM (0x6c000000),导致 DMA 失败 (错误码 0x80001110)
     const uint32_t max_read_size = PPP_PING_PONG_BUFFER_SIZE;
-    uint8_t *rx_buffer = (uint8_t *)malloc(max_read_size);
+    uint8_t *rx_buffer = (uint8_t *)osal_kmalloc(max_read_size, OSAL_GFP_KERNEL);
     if (!rx_buffer) {
         PPP_DEBUG_ERROR("PPP RX buffer alloc failed");
         g_ppp_rx_thread_completed = true;
@@ -356,7 +358,8 @@ static void ppp_lwip_receive_thread(void *arg)
     uint32_t total_bytes = 0;
     uint32_t last_timeout_check = 0;
 
-    PPP_DEBUG_INFO("PPP receive thread: allocated %d bytes temp buffer", max_read_size);
+    PPP_DEBUG_WARN("PPP receive thread: allocated %u bytes temp buffer in RAM (for DMA) at 0x%p", 
+                   max_read_size, rx_buffer);
 
     // 主循环:连续轮询UART读取
     while (g_ppp_rx_thread_running) {
@@ -570,7 +573,7 @@ static void ppp_lwip_receive_thread(void *arg)
     }
 
     // 释放缓冲区
-    free(rx_buffer);
+    osal_kfree(rx_buffer);
 
     PPP_DEBUG_INFO("PPP receive thread completed (polling mode), processed %u bytes", total_bytes);
     g_ppp_rx_thread_completed = true;
index f68ab04..84ee6f1 100644 (file)
 #define PPP_OPTIMIZED_UART_WRITE_TIMEOUT    200    /* UART写超时优化: 1000ms -> 200ms */
 #define PPP_OPTIMIZED_UART_READ_TIMEOUT     100    /* UART读超时优化: 200ms -> 100ms */
 #if defined(CONFIG_UART_SUPPORT_DMA)
-#define UART_DMA_WIDTH                         0
-#define UART_DMA_BURST_LENGTH                  2
-#define UART_DMA_PRIORITY                      0
-#define UART_DMA_TX_ENABLE                     1
+/*
+
+uint8_t src_width;          源端传输数据宽度   - 0: 1字节
+                                 *           - 1: 2字节
+                                 *           - 2: 4字节
+uint8_t dest_width;         目的端传输数据宽度 - 0: 1字节
+                                *           - 1: 2字节
+                                *           - 2: 4字节
+uint8_t burst_length;                       - 0: burst长度是1
+                                *           - 1: burst长度是4
+                                *           - 2: burst长度是8
+                                *           - 3: burst长度是16
+uint8_t priority;           传输通道优先级(最小为0以及最大为3) 
+*/
+#define UART_DMA_WIDTH                         2
+#define UART_DMA_BURST_LENGTH                  3
+#define UART_DMA_PRIORITY                      2
+#define UART_DMA_TX_ENABLE                     0
 #define UART_DMA_RX_ENABLE                     1
 #endif
 /* 串口上下文结构 - 优化缓存机制 */
@@ -42,17 +56,9 @@ typedef struct {
     uint32_t rx_tail;
     uint32_t rx_count;
     
-    /* PPP模式的发送缓冲区 */
-    uint8_t *tx_buffer;
-    uint32_t tx_buffer_size;
-    uint32_t tx_head;
-    uint32_t tx_tail;
-    uint32_t tx_count;
-    
     /* 同步对象 */
     osal_mutex rx_mutex;        // 改为结构体而不是指针
     osal_semaphore rx_semaphore; // 改为结构体而不是指针
-    osal_mutex tx_mutex;        // 发送缓冲区互斥锁
     
     /* 回调函数 */
     ppp_serial_rx_callback_t rx_callback;
@@ -76,11 +82,7 @@ static ppp_serial_context_t g_serial_ctx = {0};
 static void ppp_serial_rx_callback(const void *buffer, uint16_t length, bool remaining);
 static uint32_t ppp_serial_buffer_available_space(void);
 static uint32_t ppp_serial_buffer_data_count(void);
-static uint32_t ppp_serial_tx_buffer_available_space(void);
-static uint32_t ppp_serial_tx_buffer_data_count(void);
-static ppp_error_t ppp_serial_flush_tx_buffer_internal(void);
 static bool ppp_serial_is_ppp_control_packet(const uint8_t *data, uint32_t length);
-static bool ppp_serial_should_immediate_flush(const uint8_t *data, uint32_t length, uint32_t buffered_count);
 static uint32_t ppp_serial_get_current_time_ms(void);
 static ppp_error_t ppp_serial_register_irq(void);
 static ppp_error_t ppp_serial_unregister_irq(void);
@@ -107,7 +109,6 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
     PPP_DEBUG_DEBUG("  - TX Pin: %u", config->tx_pin);
     PPP_DEBUG_DEBUG("  - RX Pin: %u", config->rx_pin);
     PPP_DEBUG_DEBUG("  - RX Buffer Size: %u bytes", config->rx_buffer_size);
-    PPP_DEBUG_DEBUG("  - TX Buffer Size: %u bytes", config->tx_buffer_size);
     PPP_DEBUG_DEBUG("  - RX Callback: %s", config->rx_callback ? "Set" : "NULL");
 
     /* 配置UART参数 */
@@ -135,29 +136,6 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
     }
     PPP_DEBUG_DEBUG("RX buffer allocated: %u bytes at 0x%p", g_serial_ctx.rx_buffer_size, g_serial_ctx.rx_buffer);
 
-    /* 动态分配发送缓冲区 */
-    g_serial_ctx.tx_buffer_size = config->tx_buffer_size;
-    g_serial_ctx.tx_buffer = (uint8_t *)osal_kmalloc(g_serial_ctx.tx_buffer_size, OSAL_GFP_KERNEL);
-    if (g_serial_ctx.tx_buffer == NULL) {
-        PPP_DEBUG_ERROR("Failed to allocate TX buffer (%u bytes)", g_serial_ctx.tx_buffer_size);
-        osal_kfree(g_serial_ctx.rx_buffer);
-        g_serial_ctx.rx_buffer = NULL;
-        return PPP_ERR_MEMORY;
-    }
-    PPP_DEBUG_DEBUG("TX buffer allocated: %u bytes at 0x%p", g_serial_ctx.tx_buffer_size, g_serial_ctx.tx_buffer);
-
-    /* 创建发送缓冲区互斥锁 */
-    if (osal_mutex_init(&g_serial_ctx.tx_mutex) != OSAL_SUCCESS) {
-        PPP_DEBUG_ERROR("Failed to create TX mutex");
-        osal_kfree(g_serial_ctx.rx_buffer);
-        g_serial_ctx.rx_buffer = NULL;
-        osal_kfree(g_serial_ctx.tx_buffer);
-        g_serial_ctx.tx_buffer = NULL;
-        uapi_uart_deinit(g_serial_ctx.uart_bus);
-        return PPP_ERR_MEMORY;
-    }
-    PPP_DEBUG_DEBUG("TX mutex created successfully");
-
     /* 配置UART使用我们分配的接收缓冲区 */
     g_serial_ctx.buffer_config.rx_buffer = g_serial_ctx.rx_buffer;
     g_serial_ctx.buffer_config.rx_buffer_size = g_serial_ctx.rx_buffer_size;
@@ -165,9 +143,6 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
     PPP_DEBUG_DEBUG("UART buffer config:");
     PPP_DEBUG_DEBUG("  - RX Buffer Address: 0x%p", g_serial_ctx.buffer_config.rx_buffer);
     PPP_DEBUG_DEBUG("  - RX Buffer Size: %u", g_serial_ctx.buffer_config.rx_buffer_size);
-    PPP_DEBUG_DEBUG("PPP TX buffer (software managed):");
-    PPP_DEBUG_DEBUG("  - TX Buffer Address: 0x%p", g_serial_ctx.tx_buffer);
-    PPP_DEBUG_DEBUG("  - TX Buffer Size: %u", g_serial_ctx.tx_buffer_size);
 
     // errcode_t rett = uapi_uart_deinit(g_serial_ctx.uart_bus);
     // if (rett != ERRCODE_SUCC) {
@@ -180,19 +155,22 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
 
     /* 初始化UART */
     PPP_DEBUG_DEBUG("Calling uapi_uart_init...");
-    #if defined(PPP_USE_INTERRUPT_MODE) && (PPP_USE_INTERRUPT_MODE == 0)
-    // 注意:uart_porting.c中已经做了UART初始化,这里只需要设置属性
-    
     
+    // ⚠️ 修复:区分轮询模式和中断模式的UART初始化策略
+    // - 轮询模式(SUPPORT_PPP_SERVICE_POLLING):uart_porting.c中UART_BUS_0的pin=PIN_NONE,
+    //   未在启动时初始化,需要在这里完整初始化UART(但DMA已在chip_init.c中初始化)
+    // - 中断模式(SUPPORT_PPP_SERVICE_INTERRUPT):uart_porting.c中已完整初始化UART,
+    //   这里只需要设置波特率
     
-
+    #if defined(SUPPORT_PPP_SERVICE_POLLING)
+        // 轮询模式:完整初始化UART(注意:DMA已在chip_init.c:152-153初始化,不要重复调用)
+        PPP_DEBUG_WARN("Polling mode: Initializing UART for the first time");
         #if defined(CONFIG_UART_SUPPORT_DMA)
         g_serial_ctx.extra_attr.tx_dma_enable = UART_DMA_TX_ENABLE;
         g_serial_ctx.extra_attr.tx_int_threshold = 0;
         g_serial_ctx.extra_attr.rx_dma_enable = UART_DMA_RX_ENABLE;
         g_serial_ctx.extra_attr.rx_int_threshold = 0;
-        uapi_dma_init();
-        uapi_dma_open();
+        PPP_DEBUG_WARN("Polling mode with DMA: TX DMA and RX DMA both enabled");
         errcode_t ret = uapi_uart_init(g_serial_ctx.uart_bus, 
             &g_serial_ctx.pin_config,
             &g_serial_ctx.uart_attr, 
@@ -205,13 +183,12 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
             NULL, 
             &g_serial_ctx.buffer_config);
         #endif
-
+    #elif defined(SUPPORT_PPP_SERVICE_INTERRUPT)
+        // 中断模式:UART已在uart_porting.c:uart_config_init()中初始化,只设置波特率
+        PPP_DEBUG_WARN("Interrupt mode: UART already initialized, updating baudrate");
+        errcode_t ret = uapi_uart_set_attr(g_serial_ctx.uart_bus, &g_serial_ctx.uart_attr);
     #else
-    
-    // 注意:uart_porting.c中已经做了UART初始化,这里只需要设置属性 
-    // 需要配置 SUPPORT_PPP_SERVICE_INTERRUPT 才在uart_porting里初始化uart
-    errcode_t ret = uapi_uart_set_attr(g_serial_ctx.uart_bus, &g_serial_ctx.uart_attr);
-  
+        #error "Either SUPPORT_PPP_SERVICE_POLLING or SUPPORT_PPP_SERVICE_INTERRUPT must be defined"
     #endif
     if (ret != ERRCODE_SUCC) {
         PPP_DEBUG_ERROR("Failed to initialize UART: error code = %d (0x%x)", ret, ret);
@@ -219,9 +196,6 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
                        g_serial_ctx.uart_bus, config->tx_pin, config->rx_pin, config->baudrate);
         osal_kfree(g_serial_ctx.rx_buffer);
         g_serial_ctx.rx_buffer = NULL;
-        osal_kfree(g_serial_ctx.tx_buffer);
-        g_serial_ctx.tx_buffer = NULL;
-        osal_mutex_destroy(&g_serial_ctx.tx_mutex);
         return PPP_ERR_UART;
     }
     PPP_DEBUG_INFO("UART initialized successfully (error code = %d)", ret);
@@ -232,10 +206,7 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
         PPP_DEBUG_ERROR("Failed to create RX mutex");
         osal_kfree(g_serial_ctx.rx_buffer);
         g_serial_ctx.rx_buffer = NULL;
-        osal_kfree(g_serial_ctx.tx_buffer);
-        g_serial_ctx.tx_buffer = NULL;
         uapi_uart_deinit(g_serial_ctx.uart_bus);
-        osal_mutex_destroy(&g_serial_ctx.tx_mutex);
         return PPP_ERR_MEMORY;
     }
     PPP_DEBUG_DEBUG("RX mutex created successfully");
@@ -245,10 +216,7 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
         osal_mutex_destroy(&g_serial_ctx.rx_mutex);
         osal_kfree(g_serial_ctx.rx_buffer);
         g_serial_ctx.rx_buffer = NULL;
-        osal_kfree(g_serial_ctx.tx_buffer);
-        g_serial_ctx.tx_buffer = NULL;
         uapi_uart_deinit(g_serial_ctx.uart_bus);
-        osal_mutex_destroy(&g_serial_ctx.tx_mutex);
         return PPP_ERR_MEMORY;
     }
     PPP_DEBUG_DEBUG("RX semaphore created successfully");
@@ -257,9 +225,6 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
     g_serial_ctx.rx_head = 0;
     g_serial_ctx.rx_tail = 0;
     g_serial_ctx.rx_count = 0;
-    g_serial_ctx.tx_head = 0;
-    g_serial_ctx.tx_tail = 0;
-    g_serial_ctx.tx_count = 0;
     g_serial_ctx.rx_callback = config->rx_callback;
     g_serial_ctx.rx_callback_arg = config->rx_callback_arg;
 
@@ -279,7 +244,6 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config)
 
     PPP_DEBUG_DEBUG("Buffer state initialized:");
     PPP_DEBUG_DEBUG("  - RX Head/Tail/Count: %u/%u/%u", g_serial_ctx.rx_head, g_serial_ctx.rx_tail, g_serial_ctx.rx_count);
-    PPP_DEBUG_DEBUG("  - TX Head/Tail/Count: %u/%u/%u", g_serial_ctx.tx_head, g_serial_ctx.tx_tail, g_serial_ctx.tx_count);
     PPP_DEBUG_DEBUG("  - Current Mode: %d (AT)", g_serial_ctx.current_mode);
     PPP_DEBUG_DEBUG("  - Initialized Flag: %s", g_serial_ctx.initialized ? "true" : "false");
 
@@ -314,14 +278,6 @@ ppp_error_t ppp_serial_switch_to_ppp_mode(void)
     g_serial_ctx.rx_count = 0;
     osal_mutex_unlock(&g_serial_ctx.rx_mutex);
 
-    /* 清空发送缓冲区 */
-    osal_mutex_lock(&g_serial_ctx.tx_mutex);
-    g_serial_ctx.tx_head = 0;
-    g_serial_ctx.tx_tail = 0;
-    g_serial_ctx.tx_count = 0;
-    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
-    PPP_DEBUG_DEBUG("TX buffer cleared for mode switch");
-
     /* PPP数据模式:使用优化的直接UART读取,增加超时时间获取完整数据 */
     PPP_DEBUG_DEBUG("PPP Data Mode: Using optimized direct UART read with longer timeout");
     PPP_DEBUG_DEBUG("This approach is more reliable than callback mechanism");
@@ -362,16 +318,6 @@ ppp_error_t ppp_serial_switch_to_at_mode(void)
     osal_mutex_unlock(&g_serial_ctx.rx_mutex);
     PPP_DEBUG_INFO("RX buffer cleared (discarded %u bytes)", old_rx_count);
 
-    /* 清空发送缓冲区 */
-    PPP_DEBUG_DEBUG("Clearing TX buffer...");
-    osal_mutex_lock(&g_serial_ctx.tx_mutex);
-    uint32_t old_tx_count = g_serial_ctx.tx_count;
-    g_serial_ctx.tx_head = 0;
-    g_serial_ctx.tx_tail = 0;
-    g_serial_ctx.tx_count = 0;
-    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
-    PPP_DEBUG_INFO("TX buffer cleared (discarded %u bytes)", old_tx_count);
-
     /* 从PPP数据模式切换回AT模式 */
     if (g_serial_ctx.current_mode == PPP_SERIAL_MODE_PPP_DATA) {
         PPP_DEBUG_DEBUG("Switching from PPP data mode to AT mode");
@@ -644,17 +590,71 @@ ppp_error_t ppp_serial_tryread(uint8_t *buffer, uint32_t buffer_size, uint32_t *
     *bytes_read = 0;
 
     if (g_serial_ctx.current_mode == PPP_SERIAL_MODE_PPP_DATA) {
-        /* PPP数据模式:使用1ms超时快速读取,类似SLIP的sio_tryread */
-
+        /* PPP数据模式:混合策略(先轮询检测,有数据时用 DMA) */
         #if defined(CONFIG_UART_SUPPORT_DMA)
-        uart_write_dma_config_t dma_cfg = {
-            .src_width = UART_DMA_WIDTH,
-            .dest_width = UART_DMA_WIDTH,
-            .burst_length = UART_DMA_BURST_LENGTH,
-            .priority = UART_DMA_PRIORITY
-        };
-        int32_t read_result = uapi_uart_read_by_dma(g_serial_ctx.uart_bus, buffer, buffer_size,&dma_cfg);
+        // ⚠️ 核心问题:uapi_uart_read_by_dma 会阻塞 1 秒等待数据,不适合无数据时的轮询
+        // 解决方案:先用普通读取(timeout=0)快速检测,有数据时再用 DMA 批量读取
+        
+        // 第 1 步:非阻塞检测是否有数据(立即返回)
+        uint8_t probe_buf[8];
+        int32_t probe_result = uapi_uart_read(g_serial_ctx.uart_bus, probe_buf, sizeof(probe_buf), 0);
+        
+        int32_t read_result = 0;
+        
+        if (probe_result > 0) {
+            // 有数据!先复制探测数据,再用 DMA 读取剩余数据
+            static uint32_t dma_call_count = 0;
+            static uint32_t dma_success_count = 0;
             
+            // 复制探测数据
+            if ((uint32_t)probe_result <= buffer_size) {
+                memcpy(buffer, probe_buf, probe_result);
+                read_result = probe_result;
+            }
+            
+            // 如果 buffer 还有空间,尝试用 DMA 批量读取剩余数据
+            if ((uint32_t)probe_result < buffer_size) {
+                uint32_t remaining = buffer_size - probe_result;
+                // DMA 读取策略:既然已确认有数据,就充分利用 DMA 批量传输能力
+                // 只对足够大的块使用 DMA(>=64字节),小块数据用 DMA 开销反而更大
+                uint32_t dma_size = (remaining >= 64) ? remaining : 0;
+                
+                if (dma_size > 0) {
+                    uart_write_dma_config_t dma_cfg = {
+                        .src_width = UART_DMA_WIDTH,
+                        .dest_width = UART_DMA_WIDTH,
+                        .burst_length = UART_DMA_BURST_LENGTH,
+                        .priority = UART_DMA_PRIORITY
+                    };
+                    
+                    dma_call_count++;
+                    if (dma_call_count == 1) {
+                        PPP_DEBUG_WARN("=== Hybrid Mode: Poll + DMA ===");
+                        PPP_DEBUG_WARN("Poll detects data (instant), DMA reads bulk (8-64 bytes)");
+                    }
+                    
+                    int32_t dma_result = uapi_uart_read_by_dma(g_serial_ctx.uart_bus, 
+                                                               buffer + probe_result, 
+                                                               dma_size, &dma_cfg);
+                    
+                    if (dma_result > 0) {
+                        read_result += dma_result;
+                        dma_success_count++;
+                        if (dma_success_count == 1 || dma_success_count % 50 == 0) {
+                            PPP_DEBUG_WARN("DMA Success #%u: poll %d + DMA %d = %d bytes", 
+                                          dma_success_count, probe_result, dma_result, read_result);
+                        }
+                    } else if (dma_result < 0 && dma_call_count <= 5) {
+                        PPP_DEBUG_ERROR("DMA failed (%d), but poll got %d bytes", 
+                                       dma_result, probe_result);
+                    }
+                }
+            }
+        } else {
+            // 没有数据,立即返回(无阻塞)
+            read_result = 0;
+        }
+        
         #else
         int32_t read_result = uapi_uart_read(g_serial_ctx.uart_bus, buffer, buffer_size, 0);
         #endif
@@ -754,82 +754,9 @@ static bool ppp_serial_is_ppp_control_packet(const uint8_t *data, uint32_t lengt
     }
 }
 
-/**
- * @brief 智能flush决策函数
- */
-static bool ppp_serial_should_immediate_flush(const uint8_t *data, uint32_t length, uint32_t buffered_count)
-{
-    uint32_t current_time = ppp_serial_get_current_time_ms();
-    uint32_t time_since_last_tx = current_time - g_serial_ctx.last_tx_time;
-    
-    // 1. PPP控制包立即发送(最高优先级)
-    if (ppp_serial_is_ppp_control_packet(data, length)) {
-        PPP_DEBUG_INFO("PPP control packet detected, immediate flush");
-        return true;
-    }
-    
-    // 2. 缓冲区接近满(87.5%阈值,比原来的75%更保守)
-    if (buffered_count >= (g_serial_ctx.tx_buffer_size * 7 / 8)) {
-        PPP_DEBUG_INFO("Buffer nearly full (%u/%u), immediate flush", 
-                      buffered_count, g_serial_ctx.tx_buffer_size);
-        return true;
-    }
-    
-    // 3. 大包立即发送(降低阈值到128字节,避免分片)
-    if (length >= 128) {
-        PPP_DEBUG_INFO("Large packet (%u bytes), immediate flush", length);
-        return true;
-    }
-    
-    // 4. 空闲时间超过阈值
-    if (time_since_last_tx >= g_serial_ctx.idle_flush_threshold) {
-        PPP_DEBUG_INFO("Idle timeout (%u ms), immediate flush", time_since_last_tx);
-        return true;
-    }
-    
-    // 5. 连续小包累积策略
-    if (length <= 32) {
-        g_serial_ctx.consecutive_small_packets++;
-        if (g_serial_ctx.consecutive_small_packets >= 3) {
-            PPP_DEBUG_INFO("Multiple small packets accumulated (%u), immediate flush", 
-                          g_serial_ctx.consecutive_small_packets);
-            g_serial_ctx.consecutive_small_packets = 0;
-            return true;
-        }
-    } else {
-        g_serial_ctx.consecutive_small_packets = 0;
-    }
-    
-    return false;
-}
-
 /**
  * @brief 定时flush检查函数
  */
-ppp_error_t ppp_serial_periodic_flush(void)
-{
-    if (!g_serial_ctx.initialized || g_serial_ctx.current_mode != PPP_SERIAL_MODE_PPP_DATA) {
-        return PPP_ERR_INVALID_PARAM;
-    }
-    
-    uint32_t current_time = ppp_serial_get_current_time_ms();
-    uint32_t time_since_last_tx = current_time - g_serial_ctx.last_tx_time;
-    
-    osal_mutex_lock(&g_serial_ctx.tx_mutex);
-    uint32_t buffered_count = g_serial_ctx.tx_count;
-    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
-    
-    // 如果有缓冲数据且空闲时间超过阈值,强制flush
-    if (buffered_count > 0 && time_since_last_tx >= g_serial_ctx.idle_flush_threshold) {
-        PPP_DEBUG_INFO("Periodic flush: %u bytes after %u ms idle", 
-                      buffered_count, time_since_last_tx);
-        g_serial_ctx.last_tx_time = current_time;
-        return ppp_serial_flush_tx();
-    }
-    
-    return PPP_ERR_OK;
-} 
-
 /**
  * @brief 清空接收缓冲区
  */
@@ -887,15 +814,10 @@ void ppp_serial_deinit(void)
         osal_kfree(g_serial_ctx.rx_buffer);
         g_serial_ctx.rx_buffer = NULL;
     }
-    if (g_serial_ctx.tx_buffer) {
-        osal_kfree(g_serial_ctx.tx_buffer);
-        g_serial_ctx.tx_buffer = NULL;
-    }
 
     /* 销毁同步对象 */
     osal_mutex_destroy(&g_serial_ctx.rx_mutex);
     osal_sem_destroy(&g_serial_ctx.rx_semaphore);
-    osal_mutex_destroy(&g_serial_ctx.tx_mutex);
 
     /* 清理上下文 */
     memset_s(&g_serial_ctx, sizeof(g_serial_ctx), 0, sizeof(g_serial_ctx));
@@ -929,10 +851,9 @@ ppp_error_t ppp_serial_get_stats(ppp_serial_stats_t *stats)
     stats->rx_buffer_size = g_serial_ctx.rx_buffer_size;
     osal_mutex_unlock(&g_serial_ctx.rx_mutex);
     
-    osal_mutex_lock(&g_serial_ctx.tx_mutex);
-    stats->tx_buffer_usage = g_serial_ctx.tx_count;
-    stats->tx_buffer_size = g_serial_ctx.tx_buffer_size;
-    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
+    // TX buffer removed - no longer used (direct UART write)
+    stats->tx_buffer_usage = 0;
+    stats->tx_buffer_size = 0;
 
     return PPP_ERR_OK;
 }
@@ -1022,153 +943,9 @@ static uint32_t ppp_serial_buffer_data_count(void)
     return g_serial_ctx.rx_count;
 }
 
-/**
- * @brief 获取发送缓冲区可用空间
- */
-static uint32_t ppp_serial_tx_buffer_available_space(void)
-{
-    return g_serial_ctx.tx_buffer_size - g_serial_ctx.tx_count;
-}
-
-/**
- * @brief 获取发送缓冲区数据数量
- */
-static uint32_t ppp_serial_tx_buffer_data_count(void)
-{
-    return g_serial_ctx.tx_count;
-}
-
-/**
- * @brief 清空发送缓冲区
- */
-static ppp_error_t ppp_serial_flush_tx_buffer_internal(void)
-{
-    if (!g_serial_ctx.initialized) {
-        return PPP_ERR_INVALID_PARAM;
-    }
-
-    PPP_DEBUG_INFO("Flushing TX buffer...");
-    osal_mutex_lock(&g_serial_ctx.tx_mutex);
-
-    uint32_t old_count = g_serial_ctx.tx_count;
-    g_serial_ctx.tx_head = 0;
-    g_serial_ctx.tx_tail = 0;
-    g_serial_ctx.tx_count = 0;
-
-    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
-    PPP_DEBUG_INFO("TX buffer flushed (discarded %u bytes)", old_count);
-    return PPP_ERR_OK;
-}
-
-
-/**
- * @brief 强制发送缓冲区中的所有数据
- */
-ppp_error_t ppp_serial_flush_tx(void)
-{
-    if (!g_serial_ctx.initialized) {
-        PPP_DEBUG_ERROR("PPP serial not initialized");
-        return PPP_ERR_INVALID_PARAM;
-    }
-
-    PPP_DEBUG_INFO("=== TX Buffer Flush Start ===");
-    
-    osal_mutex_lock(&g_serial_ctx.tx_mutex);
-    
-    uint32_t data_count = ppp_serial_tx_buffer_data_count();
-    if (data_count == 0) {
-        osal_mutex_unlock(&g_serial_ctx.tx_mutex);
-        PPP_DEBUG_INFO("TX buffer is empty, nothing to flush");
-        PPP_DEBUG_INFO("=== TX Buffer Flush End ===");
-        return PPP_ERR_OK;
-    }
-    
-    PPP_DEBUG_INFO("Flushing %u bytes from TX buffer", data_count);
-    
-    /* 创建临时缓冲区来存储要发送的数据 */
-    uint8_t *temp_buffer = (uint8_t *)osal_kmalloc(data_count, OSAL_GFP_KERNEL);
-    if (temp_buffer == NULL) {
-        osal_mutex_unlock(&g_serial_ctx.tx_mutex);
-        PPP_DEBUG_ERROR("Failed to allocate temporary buffer for flush");
-        return PPP_ERR_MEMORY;
-    }
-    
-    /* 从环形缓冲区复制数据到临时缓冲区 */
-    for (uint32_t i = 0; i < data_count; i++) {
-        temp_buffer[i] = g_serial_ctx.tx_buffer[g_serial_ctx.tx_tail];
-        g_serial_ctx.tx_tail = (g_serial_ctx.tx_tail + 1) % g_serial_ctx.tx_buffer_size;
-        g_serial_ctx.tx_count--;
-    }
-    
-    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
-    
-    /* 发送数据 */
-    PPP_DEBUG_INFO("Calling uapi_uart_write(bus=%u, data=%p, len=%u, timeout=1000)...", 
-                  g_serial_ctx.uart_bus, temp_buffer, data_count);
-    // PPP_DEBUG_HEXDUMP(temp_buffer, data_count);
-    
-    int32_t write_result = uapi_uart_write(g_serial_ctx.uart_bus, temp_buffer, data_count, 1000);
-    PPP_DEBUG_INFO("uapi_uart_write returned: %d (expected: %u)", write_result, data_count);
-    
-    ppp_error_t result = PPP_ERR_OK;
-    if (write_result != (int32_t)data_count) {
-        PPP_DEBUG_ERROR("UART write failed during flush: returned %d, expected %u", write_result, data_count);
-        PPP_DEBUG_ERROR("Possible causes: UART not initialized, hardware error, or timeout");
-        g_serial_ctx.tx_errors++;
-        result = PPP_ERR_UART;
-    } else {
-        g_serial_ctx.tx_bytes += data_count;
-        PPP_DEBUG_INFO("Flushed %u bytes successfully (total tx: %u bytes)", 
-                      data_count, g_serial_ctx.tx_bytes);
-    }
-    
-    /* 释放临时缓冲区 */
-    osal_kfree(temp_buffer);
-    
-    PPP_DEBUG_INFO("Flush result: %s (error code: %d)", 
-                   result == PPP_ERR_OK ? "SUCCESS" : "FAILED", result);
-    PPP_DEBUG_INFO("=== TX Buffer Flush End ===");
-    
-    return result;
-}
-
-/**
- * @brief 清空发送缓冲区(丢弃数据)
- */
-void ppp_serial_flush_tx_discard(void)
-{
-    if (!g_serial_ctx.initialized) {
-        return;
-    }
-
-    osal_mutex_lock(&g_serial_ctx.tx_mutex);
-    uint32_t old_count = g_serial_ctx.tx_count;
-    g_serial_ctx.tx_head = 0;
-    g_serial_ctx.tx_tail = 0;
-    g_serial_ctx.tx_count = 0;
-    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
-
-    PPP_DEBUG_INFO("TX buffer discarded (%u bytes)", old_count);
-}
-
-/**
- * @brief 获取发送缓冲区使用情况
- */
-uint32_t ppp_serial_tx_available(void)
-{
-    if (!g_serial_ctx.initialized) {
-        return 0;
-    }
-
-    osal_mutex_lock(&g_serial_ctx.tx_mutex);
-    uint32_t count = ppp_serial_tx_buffer_data_count();
-    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
-
-    return count;
-}
-
 /**
  * @brief 重置串口状态
+ * @note TX buffer 已移除 - 发送改为直接UART写入
  */
 ppp_error_t ppp_serial_reset(void)
 {
@@ -1179,20 +956,14 @@ ppp_error_t ppp_serial_reset(void)
         return PPP_ERR_INVALID_STATE;
     }
     
-    // 1. æ¸\85空æ\89\80æ\9c\89缓冲区
-    PPP_DEBUG_INFO("Clearing all buffers...");
+    // 1. æ¸\85空æ\8e¥æ\94缓冲区
+    PPP_DEBUG_INFO("Clearing RX buffer...");
     osal_mutex_lock(&g_serial_ctx.rx_mutex);
     g_serial_ctx.rx_head = 0;
     g_serial_ctx.rx_tail = 0;
     g_serial_ctx.rx_count = 0;
     osal_mutex_unlock(&g_serial_ctx.rx_mutex);
     
-    osal_mutex_lock(&g_serial_ctx.tx_mutex);
-    g_serial_ctx.tx_head = 0;
-    g_serial_ctx.tx_tail = 0;
-    g_serial_ctx.tx_count = 0;
-    osal_mutex_unlock(&g_serial_ctx.tx_mutex);
-    
     // 2. 重置统计信息
     g_serial_ctx.tx_bytes = 0;
     g_serial_ctx.rx_bytes = 0;