From: 孙春阳 Date: Sat, 11 Oct 2025 08:52:08 +0000 (+0800) Subject: 确认slip用的中断接收 X-Git-Tag: V1.0.9_20251128_194606_LN~267 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=c3366cd4c9fedbf2135abe96abe98ae5283c0df7;p=mirrors%2FFD230.git 确认slip用的中断接收 ppp也用的中断接收 --- diff --git a/code/sdk/build/config/target_config/brandy/config.py b/code/sdk/build/config/target_config/brandy/config.py index 5e05a9660..42cba787c 100644 --- a/code/sdk/build/config/target_config/brandy/config.py +++ b/code/sdk/build/config/target_config/brandy/config.py @@ -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', ], #添加自定义应用 diff --git a/code/sdk/drivers/chips/brandy/porting/uart/uart_porting.c b/code/sdk/drivers/chips/brandy/porting/uart/uart_porting.c index b7d33971a..de05aeee1 100644 --- a/code/sdk/drivers/chips/brandy/porting/uart/uart_porting.c +++ b/code/sdk/drivers/chips/brandy/porting/uart/uart_porting.c @@ -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, diff --git a/code/sdk/drivers/drivers/driver/uart/uart.c b/code/sdk/drivers/drivers/driver/uart/uart.c index 185443628..170486a6d 100644 --- a/code/sdk/drivers/drivers/driver/uart/uart.c +++ b/code/sdk/drivers/drivers/driver/uart/uart.c @@ -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); diff --git a/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/arch/sio.c b/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/arch/sio.c index 550595083..dc23fc6d6 100644 --- a/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/arch/sio.c +++ b/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/arch/sio.c @@ -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; } diff --git a/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/test/slip_test.c b/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/test/slip_test.c index 31432c228..ba19351ed 100644 --- a/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/test/slip_test.c +++ b/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/test/slip_test.c @@ -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); } } /** diff --git a/code/sdk/zhihui/ppp/example/ppp_at_cmd.c b/code/sdk/zhihui/ppp/example/ppp_at_cmd.c index 1acaf94c6..f9d79958e 100644 --- a/code/sdk/zhihui/ppp/example/ppp_at_cmd.c +++ b/code/sdk/zhihui/ppp/example/ppp_at_cmd.c @@ -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 *)" " }, diff --git a/code/sdk/zhihui/ppp/include/ppp_api.h b/code/sdk/zhihui/ppp/include/ppp_api.h index 3adabc7db..69eee3620 100644 --- a/code/sdk/zhihui/ppp/include/ppp_api.h +++ b/code/sdk/zhihui/ppp/include/ppp_api.h @@ -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电源是否已初始化 diff --git a/code/sdk/zhihui/ppp/include/ppp_config.h b/code/sdk/zhihui/ppp/include/ppp_config.h index e960eeaf9..3ab6a1e92 100644 --- a/code/sdk/zhihui/ppp/include/ppp_config.h +++ b/code/sdk/zhihui/ppp/include/ppp_config.h @@ -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) /* diff --git a/code/sdk/zhihui/ppp/include/ppp_serial.h b/code/sdk/zhihui/ppp/include/ppp_serial.h index 2d7f2b538..b0b393ed6 100644 --- a/code/sdk/zhihui/ppp/include/ppp_serial.h +++ b/code/sdk/zhihui/ppp/include/ppp_serial.h @@ -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 设置接收回调函数 diff --git a/code/sdk/zhihui/ppp/src/ppp_api.c b/code/sdk/zhihui/ppp/src/ppp_api.c index 731587fdf..b7e9a09b8 100644 --- a/code/sdk/zhihui/ppp/src/ppp_api.c +++ b/code/sdk/zhihui/ppp/src/ppp_api.c @@ -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测试统计信息 */ diff --git a/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c b/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c index 580b9a1f4..d9d786a11 100644 --- a/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c +++ b/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c @@ -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; diff --git a/code/sdk/zhihui/ppp/src/ppp_serial.c b/code/sdk/zhihui/ppp/src/ppp_serial.c index f68ab04d1..84ee6f153 100644 --- a/code/sdk/zhihui/ppp/src/ppp_serial.c +++ b/code/sdk/zhihui/ppp/src/ppp_serial.c @@ -16,10 +16,24 @@ #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. 清空所有缓冲区 - PPP_DEBUG_INFO("Clearing all buffers..."); + // 1. 清空接收缓冲区 + 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;