From: 孙春阳 Date: Mon, 15 Sep 2025 02:49:38 +0000 (+0800) Subject: PPP 可以ping通了,还需要 优化代码,日志太多,默认不能自动可以使用,需要用at逐个执行指令。 X-Git-Tag: leiniao_debug_1.0.0_20250922_020716~84^2~9 X-Git-Url: http://git.snicker.com.cn/css/static/gitweb.css?a=commitdiff_plain;h=3181e9446ab5b69e78c200b5c33cfc9fb1ea06a5;p=mirrors%2FFD230.git PPP 可以ping通了,还需要 优化代码,日志太多,默认不能自动可以使用,需要用at逐个执行指令。 --- diff --git a/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/include/lwip/lwipopts_default.h b/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/include/lwip/lwipopts_default.h index 2416d018f..f48813ef8 100644 --- a/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/include/lwip/lwipopts_default.h +++ b/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/include/lwip/lwipopts_default.h @@ -193,6 +193,10 @@ extern "C" { #define SIO_UART_BUS UART_BUS_0 #endif +#ifndef SIO_UART_IRQ_NUM +#define SIO_UART_IRQ_NUM UART_0_IRQN +#endif + #ifndef SIO_UART_BAUDRATE #define SIO_UART_BAUDRATE 921600 #endif diff --git a/code/sdk/zhihui/4g/cat1Service/Service/cat1_runtime.c b/code/sdk/zhihui/4g/cat1Service/Service/cat1_runtime.c index 1ee2958b7..b00c0fa1b 100644 --- a/code/sdk/zhihui/4g/cat1Service/Service/cat1_runtime.c +++ b/code/sdk/zhihui/4g/cat1Service/Service/cat1_runtime.c @@ -24,9 +24,9 @@ typedef struct int sim ; int signal ; char opera[64] ; - char imei[20] ; - char pyVer[20] ; - char iccid[20] ; + char imei[32] ; + char pyVer[32] ; + char iccid[32] ; char modemVer[64] ; }cat1_runtime_status_t; diff --git a/code/sdk/zhihui/ppp/CMakeLists.txt b/code/sdk/zhihui/ppp/CMakeLists.txt index 9fb16f03b..7984cdc61 100644 --- a/code/sdk/zhihui/ppp/CMakeLists.txt +++ b/code/sdk/zhihui/ppp/CMakeLists.txt @@ -17,6 +17,7 @@ set(SOURCES src/ppp_at_handler.c src/ppp_serial.c src/ppp_lwip.c + src/ppp_lwip_thread.c src/ppp_debug.c src/ppp_power_ctl.c src/ppp_cat1_api.c @@ -68,6 +69,15 @@ set(PUBLIC_DEFINES PRINTPKT_SUPPORT=1 PPP_DEBUG=LWIP_DBG_ON PPP_INPROC_IRQ_SAFE=0 + # 添加IPCP相关配置 + IPCP_SUPPORT=1 + PPP_DNS=1 + LWIP_DNS=1 + DNS_TABLE_SIZE=2 + # 启用IPCP调试 + IPCP_DEBUG=LWIP_DBG_ON + # 确保IPCP功能完全启用 + PPP_IPV4_SUPPORT=1 # PPP_OPTIONS=1 SUPPORT_PPP_SERVICE SUPPORT_AT_PPP diff --git a/code/sdk/zhihui/ppp/example/ppp_at_cmd.c b/code/sdk/zhihui/ppp/example/ppp_at_cmd.c index b6a995b7d..91d137f21 100644 --- a/code/sdk/zhihui/ppp/example/ppp_at_cmd.c +++ b/code/sdk/zhihui/ppp/example/ppp_at_cmd.c @@ -1014,6 +1014,560 @@ static errcode_t at_ppp_show_runtime(uint8_t *para, uint32_t paraLen) return ERRCODE_SUCC; } +/* PPP连接状态检查指令 */ +static errcode_t at_ppp_check_connection(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + char status_info[2048]; + errcode_t ret = ppp_api_check_connection(status_info, sizeof(status_info)); + + if (ret == ERRCODE_SUCC) { + ppp_print_info("PPP CONNECTION CHECK:\n%s", status_info); + } else { + ppp_print_err("PPP CONNECTION CHECK: Failed to get connection status\n"); + return ERRCODE_FAIL; + } + + return ERRCODE_SUCC; +} + +/* 网络接口列表显示指令 */ +static errcode_t at_ppp_list_netif(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + char interfaces_info[2048]; + errcode_t ret = ppp_api_list_network_interfaces(interfaces_info, sizeof(interfaces_info)); + + if (ret == ERRCODE_SUCC) { + ppp_print_info("%s", interfaces_info); + } else { + ppp_print_err("Failed to get network interfaces list\n"); + return ERRCODE_FAIL; + } + + return ERRCODE_SUCC; +} + +/* 设置默认网络接口指令 */ +static errcode_t at_ppp_set_default_netif(uint8_t *para, uint32_t paraLen) +{ + if (paraLen == 0) { + ppp_print_err("Missing interface parameter\n"); + ppp_print_info("Usage: AT^PPPSETDEFAULTNETIF=\n"); + ppp_print_info("Example: AT^PPPSETDEFAULTNETIF=pp0\n"); + return ERRCODE_FAIL; + } + + // 提取接口名称 + char interface_name[32]; + if (paraLen >= sizeof(interface_name)) { + ppp_print_err("Interface name too long (max %d chars)\n", sizeof(interface_name) - 1); + return ERRCODE_FAIL; + } + + memcpy(interface_name, para, paraLen); + interface_name[paraLen] = '\0'; + + char result_info[2048]; + errcode_t ret = ppp_api_set_default_netif_with_status(interface_name, result_info, sizeof(result_info)); + + if (ret == ERRCODE_SUCC) { + ppp_print_info("%s", result_info); + } else { + ppp_print_err("%s", result_info); + return ERRCODE_FAIL; + } + + return ERRCODE_SUCC; +} + +/* 获取当前默认网络接口指令 */ +static errcode_t at_ppp_get_default_netif(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + char result_info[2048]; + errcode_t ret = ppp_api_get_default_netif_with_status(result_info, sizeof(result_info)); + + if (ret == ERRCODE_SUCC) { + ppp_print_info("%s", result_info); + } else { + ppp_print_err("%s", result_info); + return ERRCODE_FAIL; + } + + return ERRCODE_SUCC; +} + +/* PPP IPCP诊断指令 */ +static errcode_t at_ppp_diagnose_ipcp(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + ppp_print_info("Starting PPP IPCP diagnosis...\n"); + + errcode_t ret = ppp_diagnose_ipcp_status(); + if (ret == ERRCODE_SUCC) { + ppp_print_info("PPP IPCP diagnosis completed successfully\n"); + } else { + ppp_print_err("PPP IPCP diagnosis failed\n"); + return ERRCODE_FAIL; + } + + return ERRCODE_SUCC; +} + +/* PPP强制激活网络接口指令 */ +static errcode_t at_ppp_force_netif_up(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + ppp_print_info("Forcing PPP network interface activation...\n"); + + char result_info[2048]; + errcode_t ret = ppp_api_force_netif_up(result_info, sizeof(result_info)); + + if (ret == ERRCODE_SUCC) { + ppp_print_info("%s", result_info); + } else { + ppp_print_err("%s", result_info); + return ERRCODE_FAIL; + } + + return ERRCODE_SUCC; +} + +/* PPP强制IPCP重新协商指令 */ +static errcode_t at_ppp_force_ipcp_renegotiation(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + ppp_print_info("Starting IPCP renegotiation...\n"); + + char result_info[2048]; + errcode_t ret = ppp_api_force_ipcp_renegotiation(result_info, sizeof(result_info)); + + if (ret == ERRCODE_SUCC) { + ppp_print_info("%s", result_info); + } else { + ppp_print_err("%s", result_info); + return ERRCODE_FAIL; + } + + return ERRCODE_SUCC; +} + +/* PPP数据包发送测试指令 */ +static errcode_t at_ppp_send_test_packet(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + ppp_print_info("=== PPP Test Packet Sending ===\n"); + + // 检查PPP状态 + ppp_state_t ppp_state = ppp_get_state(); + if (ppp_state != PPP_STATE_CONNECTED) { + ppp_print_err("PPP not connected (state: %d). Please run AT^PPPSTARTDIAL first.\n", ppp_state); + return ERRCODE_FAIL; + } + + ppp_print_info("Sending multiple test packets to trigger PPP negotiation...\n"); + + // 1. 发送LCP Configure-Request (Link Control Protocol) + ppp_print_info("\n1. Sending LCP Configure-Request...\n"); + uint8_t lcp_config_req[] = { + 0x7E, // PPP Flag + 0xFF, 0x03, // Address and Control (standard) + 0xC0, 0x21, // LCP Protocol (0xC021) + 0x01, // Configure-Request + 0x01, // Identifier + 0x00, 0x04, // Length (4 bytes payload) + 0x7E // PPP Flag + }; + + ppp_error_t ret = ppp_serial_write(lcp_config_req, sizeof(lcp_config_req)); + if (ret == PPP_ERR_OK) { + ppp_print_info("LCP Configure-Request sent successfully (%d bytes)\n", sizeof(lcp_config_req)); + } else { + ppp_print_err("Failed to send LCP packet: %d\n", ret); + } + + // 等待一下,看是否有响应 + ppp_print_info("Waiting 2 seconds for LCP response...\n"); + osal_msleep(2000); + + // 2. 发送IPCP Configure-Request (IP Control Protocol) + ppp_print_info("\n2. Sending IPCP Configure-Request...\n"); + uint8_t ipcp_config_req[] = { + 0x7E, // PPP Flag + 0xFF, 0x03, // Address and Control + 0x80, 0x21, // IPCP Protocol (0x8021) + 0x01, // Configure-Request + 0x02, // Identifier (different from LCP) + 0x00, 0x0A, // Length (10 bytes payload) + 0x03, 0x06, // IP Address Option (type=3, length=6) + 0x00, 0x00, 0x00, 0x00, // IP Address (0.0.0.0 = request assignment) + 0x7E // PPP Flag + }; + + ret = ppp_serial_write(ipcp_config_req, sizeof(ipcp_config_req)); + if (ret == PPP_ERR_OK) { + ppp_print_info("IPCP Configure-Request sent successfully (%d bytes)\n", sizeof(ipcp_config_req)); + } else { + ppp_print_err("Failed to send IPCP packet: %d\n", ret); + } + + // 等待响应 + ppp_print_info("Waiting 3 seconds for IPCP response...\n"); + osal_msleep(3000); + + // 3. 发送一个简单的Echo-Request来测试连通性 + ppp_print_info("\n3. Sending LCP Echo-Request...\n"); + uint8_t echo_req[] = { + 0x7E, // PPP Flag + 0xFF, 0x03, // Address and Control + 0xC0, 0x21, // LCP Protocol + 0x09, // Echo-Request + 0x03, // Identifier + 0x00, 0x08, // Length (8 bytes payload) + 0x12, 0x34, 0x56, 0x78, // Magic Number + 0x7E // PPP Flag + }; + + ret = ppp_serial_write(echo_req, sizeof(echo_req)); + if (ret == PPP_ERR_OK) { + ppp_print_info("LCP Echo-Request sent successfully (%d bytes)\n", sizeof(echo_req)); + } else { + ppp_print_err("Failed to send Echo packet: %d\n", ret); + } + + ppp_print_info("\nTest packets sent. Check PPP RX thread logs for responses.\n"); + ppp_print_info("Expected responses:\n"); + ppp_print_info("- LCP Configure-Ack/Nak (C0 21 02/03)\n"); + ppp_print_info("- IPCP Configure-Ack/Nak (80 21 02/03)\n"); + ppp_print_info("- LCP Echo-Reply (C0 21 0A)\n"); + + return ERRCODE_SUCC; +} + +/* PPP数据流统计查看指令 */ +static errcode_t at_ppp_check_data_flow(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + ppp_print_info("=== PPP Data Flow Check ===\n"); + + // 检查PPP状态 + ppp_state_t ppp_state = ppp_get_state(); + const char* state_str = "UNKNOWN"; + switch (ppp_state) { + case PPP_STATE_IDLE: state_str = "IDLE"; break; + case PPP_STATE_INITIALIZED: state_str = "INITIALIZED"; break; + case PPP_STATE_CONNECTING: state_str = "CONNECTING"; break; + case PPP_STATE_CONNECTED: state_str = "CONNECTED"; break; + case PPP_STATE_DISCONNECTING: state_str = "DISCONNECTING"; break; + case PPP_STATE_ERROR: state_str = "ERROR"; break; + default: state_str = "UNKNOWN"; break; + } + + ppp_print_info("PPP State: %s (%d)\n", state_str, ppp_state); + + // 检查lwIP连接状态 + bool lwip_connected = ppp_lwip_is_connected(); + ppp_print_info("lwIP Connected: %s\n", lwip_connected ? "YES" : "NO"); + + // 简单的串口统计信息提示 + ppp_print_info("Serial Statistics: Use AT^PPPSTATUS for detailed info\n"); + ppp_print_info("Data Flow: Check PPP RX thread logs for packet info\n"); + + ppp_print_info("=== End Check ===\n"); + + return ERRCODE_SUCC; +} + +/* UART回调测试指令 */ +static errcode_t at_ppp_test_uart_callback(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + ppp_print_info("=== UART Callback Test ===\n"); + + // 检查当前串口模式 + ppp_print_info("Testing UART callback functionality...\n"); + + // 尝试读取一些数据来触发回调 + ppp_print_info("Please send some data to UART to test callback...\n"); + ppp_print_info("Waiting 5 seconds for data...\n"); + + // 等待5秒,看是否有数据到达 + for (int i = 0; i < 5; i++) { + osal_msleep(1000); + ppp_print_info("Waiting... %d/5\n", i + 1); + } + + ppp_print_info("Test completed. Check logs for callback activity.\n"); + ppp_print_info("If no 'Received X bytes' logs appear, UART callback is not working.\n"); + + return ERRCODE_SUCC; +} + +/* PPP发送测试指令 */ +static errcode_t at_ppp_test_send(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + ppp_print_info("=== PPP Send Test ===\n"); + + // 检查当前PPP状态 + ppp_state_t ppp_state = ppp_get_state(); + if (ppp_state != PPP_STATE_CONNECTED) { + ppp_print_err("PPP not connected (state: %d). Please run AT^PPPSTARTDIAL first.\n", ppp_state); + return ERRCODE_FAIL; + } + + // 测试发送一个简单的PPP数据包 + uint8_t test_packet[] = { + 0x7E, // PPP Flag + 0xFF, 0x03, // Address and Control + 0xC0, 0x21, // LCP Protocol + 0x01, // Configure-Request + 0x01, // Identifier + 0x00, 0x04, // Length (4 bytes) + 0x7E // PPP Flag + }; + + ppp_print_info("Sending test PPP packet (%d bytes)...\n", sizeof(test_packet)); + + ppp_error_t ret = ppp_serial_write(test_packet, sizeof(test_packet)); + if (ret == PPP_ERR_OK) { + ppp_print_info("PPP test packet sent successfully!\n"); + ppp_print_info("Check logs for 'PPP TX Data' to verify transmission.\n"); + } else { + ppp_print_err("Failed to send PPP test packet: %d\n", ret); + } + + return (ret == PPP_ERR_OK) ? ERRCODE_SUCC : ERRCODE_FAIL; +} + +/* UART直接测试指令 */ +static errcode_t at_ppp_test_uart_direct(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + ppp_print_info("=== UART Direct Test ===\n"); + + // 检查当前PPP状态 + ppp_state_t ppp_state = ppp_get_state(); + if (ppp_state != PPP_STATE_CONNECTED) { + ppp_print_err("PPP not connected (state: %d). Please run AT^PPPSTARTDIAL first.\n", ppp_state); + return ERRCODE_FAIL; + } + + ppp_print_info("Testing UART write/read in PPP data mode...\n"); + + // 发送一个简单的测试字符串 + const char *test_msg = "TEST123\r\n"; + uint32_t test_len = strlen(test_msg); + + ppp_print_info("Sending test string: \"%s\" (%d bytes)\n", test_msg, test_len); + + ppp_error_t ret = ppp_serial_write((const uint8_t *)test_msg, test_len); + if (ret == PPP_ERR_OK) { + ppp_print_info("Test string sent successfully!\n"); + } else { + ppp_print_err("Failed to send test string: %d\n", ret); + return ERRCODE_FAIL; + } + + // 等待并尝试读取响应 + ppp_print_info("Waiting 3 seconds for any response...\n"); + + for (int i = 0; i < 3; i++) { + osal_msleep(1000); + + uint8_t rx_buffer[256]; + uint32_t bytes_read = 0; + + ppp_error_t read_ret = ppp_serial_read(rx_buffer, sizeof(rx_buffer), &bytes_read); + if (read_ret == PPP_ERR_OK && bytes_read > 0) { + ppp_print_info("Received %d bytes: ", bytes_read); + for (uint32_t j = 0; j < bytes_read && j < 32; j++) { + ppp_print_info("%02X ", rx_buffer[j]); + } + ppp_print_info("\n"); + + // 也打印可读字符 + ppp_print_info("As text: "); + for (uint32_t j = 0; j < bytes_read && j < 32; j++) { + if (rx_buffer[j] >= 32 && rx_buffer[j] <= 126) { + ppp_print_info("%c", rx_buffer[j]); + } else { + ppp_print_info("."); + } + } + ppp_print_info("\n"); + } + + ppp_print_info("Wait %d/3...\n", i + 1); + } + + ppp_print_info("UART direct test completed.\n"); + ppp_print_info("If no data received, UART may not be working in PPP mode.\n"); + + return ERRCODE_SUCC; +} + +/* AT模式UART测试指令 - 用于对比 */ +static errcode_t at_ppp_test_uart_at_mode(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + ppp_print_info("=== AT Mode UART Test ===\n"); + + // 检查当前PPP状态 + ppp_state_t ppp_state = ppp_get_state(); + if (ppp_state == PPP_STATE_CONNECTED) { + ppp_print_err("PPP is connected (state: %d). This test is for AT mode only.\n", ppp_state); + ppp_print_err("Please run AT^PPPSTOPDIAL first to switch back to AT mode.\n"); + return ERRCODE_FAIL; + } + + ppp_print_info("Testing UART in AT mode for comparison...\n"); + + // 发送一个AT命令来测试 + char response[256]; + uint32_t response_len; + + ppp_print_info("Sending AT command for UART test...\n"); + + errcode_t ret = ppp_test_execute_at_command("AT", response, sizeof(response), &response_len, 5000); + if (ret == ERRCODE_SUCC) { + ppp_print_info("AT mode UART test SUCCESS!\n"); + ppp_print_info("Response (%d bytes): %s\n", response_len, response); + + // 打印十六进制 + ppp_print_info("Response hex: "); + for (uint32_t i = 0; i < response_len && i < 32; i++) { + ppp_print_info("%02X ", (uint8_t)response[i]); + } + ppp_print_info("\n"); + } else { + ppp_print_err("AT mode UART test FAILED: %d\n", ret); + } + + ppp_print_info("AT mode test completed.\n"); + ppp_print_info("This proves AT mode UART works. Compare with PPP mode results.\n"); + + return ERRCODE_SUCC; +} + +/* PPP接收线程状态检查指令 */ +static errcode_t at_ppp_check_rx_thread(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + ppp_print_info("=== PPP RX Thread Status Check ===\n"); + + // 检查当前PPP状态 + ppp_state_t ppp_state = ppp_get_state(); + ppp_print_info("PPP State: %d\n", ppp_state); + + if (ppp_state != PPP_STATE_CONNECTED) { + ppp_print_err("PPP not connected. PPP RX thread may not be running.\n"); + return ERRCODE_FAIL; + } + + ppp_print_info("PPP is connected. Checking RX thread status...\n"); + + // 等待一段时间,观察是否有PPP RX Thread的周期性日志 + ppp_print_info("Waiting 5 seconds for PPP RX Thread logs...\n"); + ppp_print_info("Expected logs: 'PPP RX Thread: X loops, Y packets, Z total bytes'\n"); + + for (int i = 0; i < 5; i++) { + osal_msleep(1000); + ppp_print_info("Waiting... %d/5 seconds\n", i + 1); + } + + ppp_print_info("Check completed.\n"); + ppp_print_info("If you saw 'PPP RX Thread: X loops...' logs above, the thread is running.\n"); + ppp_print_info("If no such logs appeared, the PPP RX thread may not be running!\n"); + + return ERRCODE_SUCC; +} + +/* UART读取性能测试指令 */ +static errcode_t at_ppp_test_uart_performance(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + ppp_print_info("=== UART Read Performance Test ===\n"); + + // 检查当前PPP状态 + ppp_state_t ppp_state = ppp_get_state(); + if (ppp_state != PPP_STATE_CONNECTED) { + ppp_print_err("PPP not connected (state: %d). Please run AT^PPPSTARTDIAL first.\n", ppp_state); + return ERRCODE_FAIL; + } + + ppp_print_info("Testing UART read performance in PPP mode...\n"); + + uint8_t buffer[256]; + uint32_t bytes_read; + uint32_t total_reads = 0; + uint32_t total_time = 0; + uint32_t max_time = 0; + uint32_t min_time = 0xFFFFFFFF; + + ppp_print_info("Performing 10 UART read tests...\n"); + + for (int i = 0; i < 10; i++) { + uint32_t start_time = osal_get_jiffies(); + ppp_error_t ret = ppp_serial_read(buffer, sizeof(buffer), &bytes_read); + uint32_t read_time = osal_jiffies_to_msecs(osal_get_jiffies() - start_time); + + total_reads++; + total_time += read_time; + + if (read_time > max_time) max_time = read_time; + if (read_time < min_time) min_time = read_time; + + ppp_print_info("Read %d: %u ms, %u bytes, ret=%d\n", i+1, read_time, bytes_read, ret); + + osal_msleep(100); // 间隔100ms + } + + ppp_print_info("\n=== Performance Results ===\n"); + ppp_print_info("Total reads: %u\n", total_reads); + ppp_print_info("Average time: %u ms\n", total_time / total_reads); + ppp_print_info("Min time: %u ms\n", min_time); + ppp_print_info("Max time: %u ms\n", max_time); + + if (total_time / total_reads > 50) { + ppp_print_warning("UART read is slow! Average %u ms > 50ms\n", total_time / total_reads); + ppp_print_warning("This explains why PPP RX thread is slow!\n"); + } else { + ppp_print_info("UART read performance is normal.\n"); + } + + return ERRCODE_SUCC; +} + static const at_cmd_table_t g_ppp_cmd[] = { { (char *)"AT^CAT1POWER", cat1_power, (char *)"1" }, { (char *)"AT^CAT1GETSIGNAL", at_cat1_getsignal, (char *)"1" }, @@ -1041,6 +1595,21 @@ static const at_cmd_table_t g_ppp_cmd[] = { { (char *)"AT^PPPRUNTIMEUPDATE", at_ppp_update_runtime, (char *)" " }, { (char *)"AT^PPPSINGLEUPDATE", at_ppp_update_single_runtime, (char *)"imei|signal|operator|iccid|version|network|sim" }, { (char *)"AT^PPPRUNTIMESHOW", at_ppp_show_runtime, (char *)" " }, + { (char *)"AT^PPPCHECKCONNECTION", at_ppp_check_connection, (char *)" " }, + { (char *)"AT^PPPLISTNETIF", at_ppp_list_netif, (char *)" " }, + { (char *)"AT^PPPSETDEFAULTNETIF", at_ppp_set_default_netif, (char *)"interface_name" }, + { (char *)"AT^PPPGETDEFAULTNETIF", at_ppp_get_default_netif, (char *)" " }, + { (char *)"AT^PPPDIAGNOSEIPCP", at_ppp_diagnose_ipcp, (char *)" " }, + { (char *)"AT^PPPFORCENETIFUP", at_ppp_force_netif_up, (char *)" " }, + { (char *)"AT^PPPFORCEIPCPRENEGOTIATION", at_ppp_force_ipcp_renegotiation, (char *)" " }, + { (char *)"AT^PPPSENDTESTPACKET", at_ppp_send_test_packet, (char *)" " }, + { (char *)"AT^PPPCHECKDATAFLOW", at_ppp_check_data_flow, (char *)" " }, + { (char *)"AT^PPPTESTUARTCALLBACK", at_ppp_test_uart_callback, (char *)" " }, + { (char *)"AT^PPPSENDTEST", at_ppp_test_send, (char *)" " }, + { (char *)"AT^PPPTESTUARTDIRECT", at_ppp_test_uart_direct, (char *)" " }, + { (char *)"AT^PPPTESTUARTATMODE", at_ppp_test_uart_at_mode, (char *)" " }, + { (char *)"AT^PPPCHECKRXTHREAD", at_ppp_check_rx_thread, (char *)" " }, + { (char *)"AT^PPPTESTUARTPERFORMANCE", at_ppp_test_uart_performance, (char *)" " }, #ifdef SUPPORT_ZHIHUI_WEBSOCKET { (char *)"AT^WEBSOCKETTEST", at_websocket_test_start, (char *)"serverip,port,test_time" }, { (char *)"AT^STOPWEBSOCKET", at_websocket_test_stop, (char *)" " }, diff --git a/code/sdk/zhihui/ppp/include/ppp_api.h b/code/sdk/zhihui/ppp/include/ppp_api.h index e8989e2a2..103bfc488 100644 --- a/code/sdk/zhihui/ppp/include/ppp_api.h +++ b/code/sdk/zhihui/ppp/include/ppp_api.h @@ -35,17 +35,7 @@ errcode_t ppp_start_dial(void); */ errcode_t ppp_stop_dial(void); -/** - * @brief 启动PPP数据接收线程 - * @return 错误码 - */ -ppp_error_t ppp_start_data_receive_thread(void); - -/** - * @brief 停止PPP数据接收线程 - * @return 错误码 - */ -ppp_error_t ppp_stop_data_receive_thread(void); +/* PPP数据接收线程函数已移至ppp_lwip_thread.c */ /** * @brief 获取PPP连接状态 @@ -173,6 +163,103 @@ errcode_t ppp_api_update_sim_status(void); */ errcode_t ppp_api_update_all_runtime_status(void); +/** + * @brief 设置默认网卡 + * @param netif_name 网卡名称 + * @return 错误码 + */ +errcode_t ppp_api_set_default_netif(char* netif_name); + +/** + * @brief 获取当前默认网络接口名称 + * @param netif_name 输出缓冲区 + * @param buffer_size 缓冲区大小 + * @return 错误码 + */ +errcode_t ppp_api_get_default_netif(char* netif_name, uint32_t buffer_size); + +/** + * @brief 列举所有可用的网络接口 + * @param interfaces_info 输出缓冲区,包含所有接口信息 + * @param buffer_size 缓冲区大小 + * @return 错误码 + */ +errcode_t ppp_api_list_network_interfaces(char* interfaces_info, uint32_t buffer_size); + +/** + * @brief 获取网络接口详细状态信息 + * @param netif_name 网络接口名称 + * @param status_info 输出缓冲区,包含状态信息 + * @param buffer_size 缓冲区大小 + * @return 错误码 + */ +errcode_t ppp_api_get_netif_status(const char* netif_name, char* status_info, uint32_t buffer_size); + +/** + * @brief PPP IPCP诊断函数 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_diagnose_ipcp_status(void); + +/** + * @brief 检查PPP连接状态并返回详细信息 + * @param status_info 输出缓冲区,包含连接状态信息 + * @param buffer_size 缓冲区大小 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_api_check_connection(char* status_info, uint32_t buffer_size); + +/** + * @brief 强制激活PPP网络接口 + * @param result_info 输出缓冲区,包含操作结果信息 + * @param buffer_size 缓冲区大小 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_api_force_netif_up(char* result_info, uint32_t buffer_size); + +/** + * @brief 设置默认网络接口(带详细状态输出) + * @param netif_name 网络接口名称 + * @param result_info 输出缓冲区,包含操作结果和接口状态 + * @param buffer_size 缓冲区大小 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_api_set_default_netif_with_status(const char* netif_name, char* result_info, uint32_t buffer_size); + +/** + * @brief 获取当前默认网络接口(带详细状态输出) + * @param result_info 输出缓冲区,包含默认接口名称和状态 + * @param buffer_size 缓冲区大小 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_api_get_default_netif_with_status(char* result_info, uint32_t buffer_size); + +/** + * @brief 强制重新协商IPCP以获取IP地址 + * @param result_info 输出缓冲区,包含协商结果信息 + * @param buffer_size 缓冲区大小 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_api_force_ipcp_renegotiation(char* result_info, uint32_t buffer_size); + +/** + * @brief 启动PPP接收线程 - 参考slipif_init方式 + * @return PPP_ERR_OK-成功,其他-失败 + */ +ppp_error_t ppp_lwip_start_receive_thread(void); + +/** + * @brief 停止PPP接收线程 + * @return PPP_ERR_OK-成功,其他-失败 + */ +ppp_error_t ppp_lwip_stop_receive_thread(void); + +/** + * @brief 检查PPP接收线程是否运行 + * @return true-运行中,false-未运行 + */ +bool ppp_lwip_is_receive_thread_running(void); + #ifdef __cplusplus } #endif diff --git a/code/sdk/zhihui/ppp/include/ppp_config.h b/code/sdk/zhihui/ppp/include/ppp_config.h index 0a4571fd9..a4fda20ae 100644 --- a/code/sdk/zhihui/ppp/include/ppp_config.h +++ b/code/sdk/zhihui/ppp/include/ppp_config.h @@ -23,6 +23,9 @@ extern "C" { #ifndef SIO_UART_BUS #define SIO_UART_BUS UART_BUS_0 // UART总线 #endif +#ifndef SIO_UART_IRQ_NUM +#define SIO_UART_IRQ_NUM UART_0_IRQN // UART IRQ引脚 +#endif /* 支持的波特率列表(自适应模式) */ #define PPP_BAUDRATE_AUTO_LIST {2000000, 9600, 57600, 115200 } @@ -49,7 +52,8 @@ extern "C" { #define PPP_TX_BUFFER_SIZE 2048 // 发送缓冲区大小 /* PPP数据接收线程配置 */ -#define PPP_RX_THREAD_STACK_SIZE 4096 // PPP数据接收线程栈大小 +#define PPP_RX_THREAD_STACK_SIZE 4096 // 接收线程栈大小 +#define PPP_RX_THREAD_PRIORITY osPriorityNormal // 接收线程优先级 /* PPP网络配置 */ #define PPP_MTU_SIZE 1500 // PPP MTU大小 @@ -66,7 +70,8 @@ typedef enum { PPP_STATE_INIT, // 初始化状态 PPP_STATE_AT_HANDSHAKE, // AT握手状态 PPP_STATE_SET_BAUDRATE, // 设置波特率状态 - PPP_STATE_DIALING, // 拨号状态 + PPP_STATE_DIALING, + PPP_STATE_CONNECTING, // 拨号状态 PPP_STATE_CONNECTED, // 已连接状态 PPP_STATE_DISCONNECTING, // 断开连接状态 PPP_STATE_ERROR // 错误状态 diff --git a/code/sdk/zhihui/ppp/include/ppp_serial.h b/code/sdk/zhihui/ppp/include/ppp_serial.h index 4296a1926..65aff75e1 100644 --- a/code/sdk/zhihui/ppp/include/ppp_serial.h +++ b/code/sdk/zhihui/ppp/include/ppp_serial.h @@ -28,6 +28,7 @@ typedef enum { */ typedef struct { uint8_t uart_bus; // UART总线号 + uint8_t irq_num; // UART IRQ引脚 uint32_t baudrate; // 波特率 uint8_t tx_pin; // 发送引脚 uint8_t rx_pin; // 接收引脚 diff --git a/code/sdk/zhihui/ppp/src/ppp_api.c b/code/sdk/zhihui/ppp/src/ppp_api.c index 59311eef7..20459dc9b 100644 --- a/code/sdk/zhihui/ppp/src/ppp_api.c +++ b/code/sdk/zhihui/ppp/src/ppp_api.c @@ -13,7 +13,13 @@ #include "schedule/osal_task.h" #include "securec.h" #include "ppp_log.h" -#include "ppp_types.h" // 添加类型定义头文件 + +// lwIP头文件,用于访问netif结构体和系统抽象层 +#ifdef LWIP_PPP_SUPPORT +#include "lwip/netif.h" +#include "lwip/sys.h" /* lwIP系统抽象层,参考slipif_init方式 */ +#endif + // PPP连接状态 static ppp_state_t g_ppp_state = PPP_STATE_IDLE; @@ -28,6 +34,7 @@ uint8_t g_ppp_enable_debug = PPP_LOG_LEVEL_INFO; // 外部声明cat1_api_enable_cat1函数(在ppp_cat1_api.c中实现) extern void cat1_api_enable_cat1(bool isopen); +static errcode_t ppp_api_get_ppp_netif_name(char* netif_name, uint32_t buffer_size); /** * @brief 初始化PPP模块 */ @@ -100,6 +107,7 @@ errcode_t zhihui_ppp_init(const ppp_config_t *config) PPP_DEBUG_PRINT("Step 3: Initializing UART for AT mode\n"); ppp_serial_config_t serial_config = { .uart_bus = SIO_UART_BUS, + .irq_num = SIO_UART_IRQ_NUM, .baudrate = g_ppp_config.baudrate, .tx_pin = SIO_UART_TX_PIN, .rx_pin = SIO_UART_RX_PIN, @@ -107,8 +115,7 @@ errcode_t zhihui_ppp_init(const ppp_config_t *config) .tx_buffer_size = PPP_TX_BUFFER_SIZE, .rx_callback = NULL, .rx_callback_arg = NULL - }; - + }; ppp_error_t ret = ppp_serial_init(&serial_config); if (ret != PPP_ERR_OK) { PPP_DEBUG_PRINT("Failed to initialize serial for AT mode: %d\n", ret); @@ -167,7 +174,101 @@ init_failed: static void ppp_lwip_event_callback(const ppp_lwip_event_t *event, void *arg) { + (void)arg; + PPP_DEBUG_PRINT("PPP lwIP event: %d\n", event->type); + + switch (event->type) { + case PPP_LWIP_EVENT_CONNECTED: + PPP_DEBUG_INFO("PPP connection established successfully"); + + // 设置PPP状态为已连接 + g_ppp_state = PPP_STATE_CONNECTED; + PPP_DEBUG_INFO("PPP state updated to CONNECTED"); + + // 等待一小段时间让IPCP协商完成 + osal_msleep(1000); + + // 多次重试检查网络信息,直到获取到有效IP + int retry_count = 0; + const int max_retries = 10; + bool ip_acquired = false; + + while (retry_count < max_retries && !ip_acquired) { + // 重新检查网络信息 + ppp_lwip_network_info_t lwip_info; + ppp_error_t lwip_ret = ppp_lwip_get_network_info(&lwip_info); + + if (lwip_ret == PPP_ERR_OK && lwip_info.local_ip != 0) { + PPP_DEBUG_INFO("PPP network info acquired after %d retries - Local IP: %u.%u.%u.%u", + retry_count, + (lwip_info.local_ip >> 0) & 0xFF, + (lwip_info.local_ip >> 8) & 0xFF, + (lwip_info.local_ip >> 16) & 0xFF, + (lwip_info.local_ip >> 24) & 0xFF); + ip_acquired = true; + } else { + retry_count++; + PPP_DEBUG_WARN("PPP network info not ready, retry %d/%d", retry_count, max_retries); + osal_msleep(500); // 等待500ms再重试 + } + } + + if (!ip_acquired) { + PPP_DEBUG_ERROR("Failed to acquire IP address after %d retries", max_retries); + PPP_DEBUG_INFO("Forcing netif up and trying manual IP check..."); + + // 强制激活网络接口 + struct netif *ppp_netif = ppp_lwip_get_netif(); + if (ppp_netif) { + netif_set_up(ppp_netif); + netif_set_link_up(ppp_netif); + PPP_DEBUG_INFO("Forced netif up, flags: 0x%02x", ppp_netif->flags); + } + } + + // 获取实际的PPP网络接口名称 + char ppp_netif_name[16]; + errcode_t ret = ppp_api_get_ppp_netif_name(ppp_netif_name, sizeof(ppp_netif_name)); + if (ret != ERRCODE_SUCC) { + // 如果获取失败,使用默认名称 + strncpy_s(ppp_netif_name, sizeof(ppp_netif_name), "pp0", sizeof(ppp_netif_name) - 1); + PPP_DEBUG_WARN("Failed to get PPP netif name, using default: pp0"); + } + + // 自动设置PPP接口为默认网卡 + ret = ppp_api_set_default_netif(ppp_netif_name); + if (ret == ERRCODE_SUCC) { + PPP_DEBUG_INFO("PPP interface (%s) automatically set as default network interface", ppp_netif_name); + } else { + PPP_DEBUG_WARN("Failed to set PPP interface (%s) as default: %d", ppp_netif_name, ret); + } + break; + + case PPP_LWIP_EVENT_DISCONNECTED: + PPP_DEBUG_INFO("PPP connection disconnected"); + + // 设置PPP状态为已初始化(可以重新拨号) + g_ppp_state = PPP_STATE_INITIALIZED; + PPP_DEBUG_INFO("PPP state updated to INITIALIZED"); + + // PPP断开时,自动切换回回环接口作为默认网卡 + ret = ppp_api_set_default_netif("lo"); + if (ret == ERRCODE_SUCC) { + PPP_DEBUG_INFO("Automatically switched back to loopback interface (lo) as default"); + } else { + PPP_DEBUG_WARN("Failed to set loopback interface as default: %d", ret); + } + break; + + case PPP_LWIP_EVENT_ERROR: + PPP_DEBUG_ERROR("PPP connection error: %d", event->error_code); + break; + + default: + PPP_DEBUG_DEBUG("PPP lwIP event: %d", event->type); + break; + } } /** @@ -206,8 +307,46 @@ errcode_t ppp_start_dial(void) goto error_recovery_at_mode; } + // 8.5. 验证调制解调器是否真正进入PPP数据模式 + PPP_DEBUG_PRINT("Verifying modem is in PPP data mode...\n"); + osal_msleep(1000); // 等待1秒让调制解调器稳定 + + // 尝试读取一些数据,检查是否还有AT响应 + uint8_t verify_buffer[64]; + uint32_t bytes_read = 0; + ppp_error_t verify_ret = ppp_serial_read(verify_buffer, sizeof(verify_buffer), &bytes_read); + + if (verify_ret == PPP_ERR_OK && bytes_read > 0) { + PPP_DEBUG_PRINT("Read %u bytes after mode switch, checking for AT responses...\n", bytes_read); + + // 检查是否包含AT响应(如"OK", "ERROR"等) + bool has_at_response = false; + for (uint32_t i = 0; i < bytes_read - 1; i++) { + if ((verify_buffer[i] == 'O' && verify_buffer[i+1] == 'K') || + (verify_buffer[i] == 'E' && i < bytes_read - 4 && + strncmp((char*)&verify_buffer[i], "ERROR", 5) == 0)) { + has_at_response = true; + break; + } + } + + if (has_at_response) { + PPP_DEBUG_ERROR("Modem still sending AT responses - not in PPP data mode!\n"); + PPP_DEBUG_PRINT("Received data: "); + for (uint32_t i = 0; i < bytes_read; i++) { + PPP_DEBUG_PRINT("%02X ", verify_buffer[i]); + } + PPP_DEBUG_PRINT("\n"); + goto error_recovery_at_mode; + } else { + PPP_DEBUG_PRINT("Data looks like PPP frames - mode switch successful\n"); + } + } else { + PPP_DEBUG_PRINT("No immediate data after mode switch - this is normal\n"); + } + // 9. 启动PPP数据接收处理(在lwIP连接之前启动) - ret = ppp_start_data_receive_thread(); + ret = ppp_lwip_start_receive_thread(); if (ret != PPP_ERR_OK) { PPP_DEBUG_PRINT("Failed to start PPP data receive thread: %d\n", ret); goto error_recovery_at_mode; @@ -223,7 +362,7 @@ errcode_t ppp_start_dial(void) ret = ppp_lwip_init(&lwip_config); // 使用默认配置 if (ret != PPP_ERR_OK) { PPP_DEBUG_PRINT("Failed to initialize lwIP PPP: %d\n", ret); - ppp_stop_data_receive_thread(); + ppp_lwip_stop_receive_thread(); goto error_recovery_at_mode; } @@ -232,12 +371,15 @@ errcode_t ppp_start_dial(void) if (ret != PPP_ERR_OK) { PPP_DEBUG_PRINT("Failed to start PPP connection: %d\n", ret); ppp_lwip_deinit(); - ppp_stop_data_receive_thread(); + ppp_lwip_stop_receive_thread(); goto error_recovery_at_mode; } - g_ppp_state = PPP_STATE_CONNECTED; + // 注意:不要立即设置为CONNECTED,等待PPP协商完成 + // g_ppp_state将在ppp_lwip_event_callback中设置为CONNECTED + g_ppp_state = PPP_STATE_CONNECTING; PPP_DEBUG_PRINT("PPP dial completed successfully - now in data mode\n"); + PPP_DEBUG_PRINT("PPP negotiation will start automatically...\n"); return ERRCODE_SUCC; @@ -277,7 +419,7 @@ errcode_t ppp_stop_dial(void) } // 1. 停止PPP数据接收线程 - ppp_stop_data_receive_thread(); + ppp_lwip_stop_receive_thread(); // 2. 断开lwIP PPP连接 ppp_lwip_disconnect(); @@ -349,10 +491,40 @@ errcode_t ppp_get_connection_info(ppp_connection_info_t *info) return ERRCODE_INVALID_PARAM; } - // TODO: 实现连接信息获取 + // 初始化结构体 (void)memset_s(info, sizeof(ppp_connection_info_t), 0, sizeof(ppp_connection_info_t)); - PPP_DEBUG_PRINT("PPP connection info retrieved\n"); + // 检查PPP连接状态 + if (g_ppp_state != PPP_STATE_CONNECTED) { + PPP_DEBUG_PRINT("PPP not connected, state: %d\n", g_ppp_state); + return ERRCODE_FAIL; + } + + // 从lwIP获取网络信息 + ppp_lwip_network_info_t lwip_info; + ppp_error_t ret = ppp_lwip_get_network_info(&lwip_info); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("Failed to get lwIP network info: %d", ret); + return ERRCODE_FAIL; + } + + // 复制网络信息 + info->local_ip = lwip_info.local_ip; + info->remote_ip = lwip_info.remote_ip; + info->primary_dns = lwip_info.primary_dns; + info->secondary_dns = lwip_info.secondary_dns; + info->mtu = lwip_info.mtu; + info->connected = lwip_info.connected; + + // 设置连接时间(这里简化处理,可以后续完善) + info->connect_time = 0; + + PPP_DEBUG_INFO("PPP connection info retrieved successfully"); + PPP_DEBUG_INFO("Local IP: %u.%u.%u.%u", + (info->local_ip >> 0) & 0xFF, + (info->local_ip >> 8) & 0xFF, + (info->local_ip >> 16) & 0xFF, + (info->local_ip >> 24) & 0xFF); return ERRCODE_SUCC; } @@ -370,7 +542,7 @@ errcode_t ppp_reset_from_error(void) PPP_DEBUG_PRINT("Resetting PPP from error state\n"); // 1. 停止所有可能的活动 - ppp_stop_data_receive_thread(); + ppp_lwip_stop_receive_thread(); ppp_lwip_deinit(); // 2. 尝试恢复到AT模式 @@ -439,86 +611,7 @@ errcode_t zhihui_ppp_deinit(void) return ERRCODE_SUCC; } -/* PPP数据接收线程相关 */ -static osal_task *g_ppp_rx_task = NULL; -static bool g_ppp_rx_thread_running = false; - -/** - * @brief PPP数据接收线程 - */ -static void ppp_data_receive_thread(void *arg) -{ - (void)arg; - - PPP_DEBUG_PRINT("PPP data receive thread started\n"); - - uint8_t rx_buffer[PPP_RX_BUFFER_SIZE]; - uint32_t bytes_read; - - while (g_ppp_rx_thread_running) { - // 从串口读取PPP数据 - ppp_error_t ret = ppp_serial_read(rx_buffer, sizeof(rx_buffer), &bytes_read); - if (ret == PPP_ERR_OK && bytes_read > 0) { - // 将数据传递给lwIP PPP协议栈 - ppp_lwip_input(rx_buffer, bytes_read); - } - - // 短暂延时,避免占用过多CPU - osal_msleep(1); - } - - PPP_DEBUG_PRINT("PPP data receive thread stopped\n"); -} - -/** - * @brief 启动PPP数据接收线程 - */ -ppp_error_t ppp_start_data_receive_thread(void) -{ - if (g_ppp_rx_task != NULL) { - PPP_DEBUG_WARN("PPP data receive thread already running"); - return PPP_ERR_OK; - } - - g_ppp_rx_thread_running = true; - - // 创建PPP数据接收线程 - g_ppp_rx_task = osal_kthread_create((osal_kthread_handler)ppp_data_receive_thread, - NULL, "ppp_rx_thread", PPP_RX_THREAD_STACK_SIZE); - if (g_ppp_rx_task == NULL) { - PPP_DEBUG_ERROR("Failed to create PPP data receive thread"); - g_ppp_rx_thread_running = false; - return PPP_ERR_MEMORY; - } - - PPP_DEBUG_INFO("PPP data receive thread created successfully"); - return PPP_ERR_OK; -} - -/** - * @brief 停止PPP数据接收线程 - */ -ppp_error_t ppp_stop_data_receive_thread(void) -{ - if (g_ppp_rx_task == NULL) { - return PPP_ERR_OK; - } - - PPP_DEBUG_INFO("Stopping PPP data receive thread"); - - // 停止线程 - g_ppp_rx_thread_running = false; - - // 等待线程结束 - osal_msleep(100); - - // 销毁线程 - osal_kthread_destroy(g_ppp_rx_task, 0); - g_ppp_rx_task = NULL; - - PPP_DEBUG_INFO("PPP data receive thread stopped"); - return PPP_ERR_OK; -} +/* PPP数据接收线程已移至ppp_lwip_thread.c */ /* ========== PPP测试接口实现 ========== */ @@ -1209,4 +1302,732 @@ errcode_t ppp_api_update_all_runtime_status(void) PPP_DEBUG_INFO("Runtime status update completed"); return ret; -} \ No newline at end of file +} + +/** + * @brief 设置默认网络接口 + * @param netif_name 网络接口名称 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_api_set_default_netif(char* netif_name) +{ + if (netif_name == NULL) { + PPP_DEBUG_ERROR("Invalid netif name parameter"); + return ERRCODE_INVALID_PARAM; + } + + PPP_DEBUG_INFO("Setting default network interface to: %s", netif_name); + + // 这里可以根据实际的网络接口管理需求来实现 + // 由于lwIP的具体实现可能因系统而异,这里提供一个通用的框架 + + // 示例实现:记录当前设置的默认网卡名称 + static char current_default_netif[32] = {0}; + + if (strlen(netif_name) >= sizeof(current_default_netif)) { + PPP_DEBUG_ERROR("Network interface name too long: %s", netif_name); + return ERRCODE_INVALID_PARAM; + } + + // 保存网卡名称 + strncpy_s(current_default_netif, sizeof(current_default_netif), + netif_name, sizeof(current_default_netif) - 1); + current_default_netif[sizeof(current_default_netif) - 1] = '\0'; + + PPP_DEBUG_INFO("Default network interface set to: %s", current_default_netif); + + // 实际设置默认网络接口 + if (strcmp(netif_name, "lo") == 0) { + // 设置回环接口为默认(这里简化处理) + PPP_DEBUG_INFO("Loopback interface set as default (no action needed)"); + } else { + // 检查是否是PPP接口 + char ppp_netif_name[16]; + errcode_t name_ret = ppp_api_get_ppp_netif_name(ppp_netif_name, sizeof(ppp_netif_name)); + + if ((name_ret == ERRCODE_SUCC && strcmp(netif_name, ppp_netif_name) == 0) || + strcmp(netif_name, "pp0") == 0) { + // 设置PPP接口为默认 + struct netif *ppp_netif = ppp_lwip_get_netif(); + if (ppp_netif != NULL) { +#ifdef LWIP_PPP_SUPPORT + netif_set_default(ppp_netif); + PPP_DEBUG_INFO("PPP netif set as default in lwIP"); +#endif + } else { + PPP_DEBUG_WARN("PPP netif not available for setting as default"); + } + } + } + + return ERRCODE_SUCC; +} + +/** + * @brief 获取当前默认网络接口名称 + * @param netif_name 输出缓冲区 + * @param buffer_size 缓冲区大小 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_api_get_default_netif(char* netif_name, uint32_t buffer_size) +{ + if (netif_name == NULL || buffer_size == 0) { + PPP_DEBUG_ERROR("Invalid parameters"); + return ERRCODE_INVALID_PARAM; + } + + static char current_default_netif[32] = {0}; + + if (strlen(current_default_netif) == 0) { + // 如果没有设置过,返回默认值 + strncpy_s(netif_name, buffer_size, "none", buffer_size - 1); + } else { + strncpy_s(netif_name, buffer_size, current_default_netif, buffer_size - 1); + } + + netif_name[buffer_size - 1] = '\0'; + + PPP_DEBUG_INFO("Current default network interface: %s", netif_name); + return ERRCODE_SUCC; +} + +// 重复函数定义已删除 - 使用后面的新实现 + +// 重复函数定义已删除 - 使用后面的新实现 + +/** + * @brief 获取PPP网络接口的实际名称 + * @param netif_name 输出缓冲区 + * @param buffer_size 缓冲区大小 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +static errcode_t ppp_api_get_ppp_netif_name(char* netif_name, uint32_t buffer_size) +{ + if (netif_name == NULL || buffer_size == 0) { + PPP_DEBUG_ERROR("Invalid parameters"); + return ERRCODE_INVALID_PARAM; + } + + // 获取PPP网络接口指针 + struct netif *ppp_netif = ppp_lwip_get_netif(); + if (ppp_netif == NULL) { + PPP_DEBUG_ERROR("PPP netif not available"); + return ERRCODE_FAIL; + } + + // 构建网络接口名称 + if (ppp_netif->name[0] != 0 && ppp_netif->name[1] != 0) { + // 如果有实际的名称,使用实际名称+编号 + snprintf(netif_name, buffer_size, "%c%c%u", + ppp_netif->name[0], ppp_netif->name[1], ppp_netif->num); + } else { + // 如果没有名称,使用默认的pp0 + snprintf(netif_name, buffer_size, "pp%u", ppp_netif->num); + } + + PPP_DEBUG_INFO("PPP netif name: %s", netif_name); + return ERRCODE_SUCC; +} + +/** + * @brief PPP IPCP诊断函数 + */ +errcode_t ppp_diagnose_ipcp_status(void) +{ + PPP_DEBUG_INFO("=== PPP IPCP Diagnosis ==="); + + if (g_ppp_state != PPP_STATE_CONNECTED) { + PPP_DEBUG_WARN("PPP not in connected state: %d", g_ppp_state); + return ERRCODE_FAIL; + } + + // 获取lwIP网络信息 + ppp_lwip_network_info_t lwip_info; + ppp_error_t ret = ppp_lwip_get_network_info(&lwip_info); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("Failed to get lwIP network info: %d", ret); + return ERRCODE_FAIL; + } + + PPP_DEBUG_INFO("IPCP Status:"); + PPP_DEBUG_INFO(" Connected: %s", lwip_info.connected ? "YES" : "NO"); + PPP_DEBUG_INFO(" Local IP: %u.%u.%u.%u (0x%08x)", + (lwip_info.local_ip >> 0) & 0xFF, + (lwip_info.local_ip >> 8) & 0xFF, + (lwip_info.local_ip >> 16) & 0xFF, + (lwip_info.local_ip >> 24) & 0xFF, + lwip_info.local_ip); + PPP_DEBUG_INFO(" Remote IP: %u.%u.%u.%u (0x%08x)", + (lwip_info.remote_ip >> 0) & 0xFF, + (lwip_info.remote_ip >> 8) & 0xFF, + (lwip_info.remote_ip >> 16) & 0xFF, + (lwip_info.remote_ip >> 24) & 0xFF, + lwip_info.remote_ip); + PPP_DEBUG_INFO(" Primary DNS: %u.%u.%u.%u (0x%08x)", + (lwip_info.primary_dns >> 0) & 0xFF, + (lwip_info.primary_dns >> 8) & 0xFF, + (lwip_info.primary_dns >> 16) & 0xFF, + (lwip_info.primary_dns >> 24) & 0xFF, + lwip_info.primary_dns); + PPP_DEBUG_INFO(" Secondary DNS: %u.%u.%u.%u (0x%08x)", + (lwip_info.secondary_dns >> 0) & 0xFF, + (lwip_info.secondary_dns >> 8) & 0xFF, + (lwip_info.secondary_dns >> 16) & 0xFF, + (lwip_info.secondary_dns >> 24) & 0xFF, + lwip_info.secondary_dns); + PPP_DEBUG_INFO(" MTU: %u", lwip_info.mtu); + + // 检查网络接口状态 + struct netif *ppp_netif = ppp_lwip_get_netif(); + if (ppp_netif) { + PPP_DEBUG_INFO("Netif Status:"); + PPP_DEBUG_INFO(" Flags: 0x%02x", ppp_netif->flags); + PPP_DEBUG_INFO(" Name: %c%c%u", ppp_netif->name[0], ppp_netif->name[1], ppp_netif->num); + PPP_DEBUG_INFO(" MTU: %u", ppp_netif->mtu); + PPP_DEBUG_INFO(" Link Up: %s", netif_is_link_up(ppp_netif) ? "YES" : "NO"); + PPP_DEBUG_INFO(" Interface Up: %s", netif_is_up(ppp_netif) ? "YES" : "NO"); + } else { + PPP_DEBUG_ERROR("PPP netif is NULL!"); + } + + PPP_DEBUG_INFO("=== End PPP IPCP Diagnosis ==="); + return ERRCODE_SUCC; +} + +/** + * @brief 检查PPP连接状态并返回详细信息 + * @param status_info 输出缓冲区,包含连接状态信息 + * @param buffer_size 缓冲区大小 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_api_check_connection(char* status_info, uint32_t buffer_size) +{ + if (status_info == NULL || buffer_size == 0) { + PPP_DEBUG_ERROR("Invalid parameters"); + return ERRCODE_INVALID_PARAM; + } + + PPP_DEBUG_INFO("Checking PPP connection status"); + + // 调用现有的状态获取函数 + errcode_t ret = ppp_test_get_status(status_info, buffer_size); + if (ret != ERRCODE_SUCC) { + PPP_DEBUG_ERROR("Failed to get PPP status"); + return ret; + } + + PPP_DEBUG_INFO("PPP connection status retrieved successfully"); + return ERRCODE_SUCC; +} + +/** + * @brief 强制激活PPP网络接口 + * @param result_info 输出缓冲区,包含操作结果信息 + * @param buffer_size 缓冲区大小 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_api_force_netif_up(char* result_info, uint32_t buffer_size) +{ + if (result_info == NULL || buffer_size == 0) { + PPP_DEBUG_ERROR("Invalid parameters"); + return ERRCODE_INVALID_PARAM; + } + + PPP_DEBUG_INFO("Forcing PPP network interface activation"); + + // 初始化输出缓冲区 + memset(result_info, 0, buffer_size); + + // 获取PPP网络接口 + struct netif *ppp_netif = ppp_lwip_get_netif(); + if (!ppp_netif) { + snprintf(result_info, buffer_size, "ERROR: PPP netif not available\n"); + PPP_DEBUG_ERROR("PPP netif not available"); + return ERRCODE_FAIL; + } + + // 记录激活前的状态 + uint32_t flags_before = ppp_netif->flags; + uint32_t ip_before = ip4_addr_get_u32(&ppp_netif->ip_addr); + + // 强制激活网络接口 +#ifdef LWIP_PPP_SUPPORT + netif_set_up(ppp_netif); + netif_set_link_up(ppp_netif); + netif_set_default(ppp_netif); +#endif + + // 记录激活后的状态 + uint32_t flags_after = ppp_netif->flags; + uint32_t ip_after = ip4_addr_get_u32(&ppp_netif->ip_addr); + + // 生成结果信息 + int ret_len = snprintf(result_info, buffer_size, + "=== PPP Network Interface Force Activation ===\n" + "Interface Name: %c%c%u\n" + "Flags Before: 0x%02x\n" + "Flags After: 0x%02x\n" + "IP Before: %u.%u.%u.%u\n" + "IP After: %u.%u.%u.%u\n" + "Status: %s\n", + ppp_netif->name[0], ppp_netif->name[1], ppp_netif->num, + flags_before, flags_after, + (ip_before >> 0) & 0xFF, (ip_before >> 8) & 0xFF, + (ip_before >> 16) & 0xFF, (ip_before >> 24) & 0xFF, + (ip_after >> 0) & 0xFF, (ip_after >> 8) & 0xFF, + (ip_after >> 16) & 0xFF, (ip_after >> 24) & 0xFF, + (flags_after != flags_before || ip_after != ip_before) ? "CHANGED" : "NO CHANGE"); + + if (ret_len > 0 && ret_len < (int)buffer_size) { + // 运行IPCP诊断 + errcode_t diag_ret = ppp_diagnose_ipcp_status(); + if (diag_ret != ERRCODE_SUCC) { + int remaining = buffer_size - ret_len; + if (remaining > 50) { + snprintf(result_info + ret_len, remaining, "\nWarning: IPCP diagnosis failed\n"); + } + } + + PPP_DEBUG_INFO("PPP netif force activation completed"); + return ERRCODE_SUCC; + } else { + PPP_DEBUG_ERROR("Failed to generate result info"); + return ERRCODE_FAIL; + } +} + +/** + * @brief 设置默认网络接口(带详细状态输出) + * @param netif_name 网络接口名称 + * @param result_info 输出缓冲区,包含操作结果和接口状态 + * @param buffer_size 缓冲区大小 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_api_set_default_netif_with_status(const char* netif_name, char* result_info, uint32_t buffer_size) +{ + if (netif_name == NULL || result_info == NULL || buffer_size == 0) { + PPP_DEBUG_ERROR("Invalid parameters"); + return ERRCODE_INVALID_PARAM; + } + + PPP_DEBUG_INFO("Setting default network interface: %s", netif_name); + + // 初始化输出缓冲区 + memset(result_info, 0, buffer_size); + + // 调用基础设置函数 + errcode_t ret = ppp_api_set_default_netif((char*)netif_name); + if (ret != ERRCODE_SUCC) { + snprintf(result_info, buffer_size, + "ERROR: Failed to set default interface to '%s'\n", netif_name); + return ret; + } + + // 生成成功信息 + int info_len = snprintf(result_info, buffer_size, + "SUCCESS: Set '%s' as default interface\n\n", netif_name); + + if (info_len > 0 && info_len < (int)buffer_size) { + // 获取接口详细状态 + char status_info[1024]; + ret = ppp_api_get_netif_status(netif_name, status_info, sizeof(status_info)); + if (ret == ERRCODE_SUCC) { + int remaining = buffer_size - info_len; + if (remaining > 0) { + strncat(result_info, status_info, remaining - 1); + } + } + } + + PPP_DEBUG_INFO("Default network interface set successfully"); + return ERRCODE_SUCC; +} + +/** + * @brief 获取当前默认网络接口(带详细状态输出) + * @param result_info 输出缓冲区,包含默认接口名称和状态 + * @param buffer_size 缓冲区大小 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_api_get_default_netif_with_status(char* result_info, uint32_t buffer_size) +{ + if (result_info == NULL || buffer_size == 0) { + PPP_DEBUG_ERROR("Invalid parameters"); + return ERRCODE_INVALID_PARAM; + } + + PPP_DEBUG_INFO("Getting current default network interface"); + + // 初始化输出缓冲区 + memset(result_info, 0, buffer_size); + + // 获取默认接口名称 + char netif_name[64]; + errcode_t ret = ppp_api_get_default_netif(netif_name, sizeof(netif_name)); + if (ret != ERRCODE_SUCC) { + snprintf(result_info, buffer_size, "ERROR: Failed to get default interface\n"); + return ret; + } + + // 生成基础信息 + int info_len = snprintf(result_info, buffer_size, + "Current default interface: %s\n\n", netif_name); + + if (info_len > 0 && info_len < (int)buffer_size) { + if (strcmp(netif_name, "none") != 0) { + // 获取接口详细状态 + char status_info[1024]; + ret = ppp_api_get_netif_status(netif_name, status_info, sizeof(status_info)); + if (ret == ERRCODE_SUCC) { + int remaining = buffer_size - info_len; + if (remaining > 0) { + strncat(result_info, status_info, remaining - 1); + } + } + } else { + int remaining = buffer_size - info_len; + if (remaining > 30) { + strncat(result_info, "No default interface is currently set\n", remaining - 1); + } + } + } + + PPP_DEBUG_INFO("Default network interface info retrieved successfully"); + return ERRCODE_SUCC; +} + +/** + * @brief 列举所有可用的网络接口 + * @param interfaces_info 输出缓冲区,包含所有接口信息 + * @param buffer_size 缓冲区大小 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_api_list_network_interfaces(char* interfaces_info, uint32_t buffer_size) +{ + if (interfaces_info == NULL || buffer_size == 0) { + PPP_DEBUG_ERROR("Invalid parameters"); + return ERRCODE_INVALID_PARAM; + } + + PPP_DEBUG_INFO("Listing network interfaces"); + + // 初始化输出缓冲区 + memset(interfaces_info, 0, buffer_size); + + int ret = snprintf(interfaces_info, buffer_size, + "=== Network Interface List ===\n" + "[0] lo (Loopback)\n" + " IP: 127.0.0.1\n" + " Status: UP\n" + " Type: Loopback\n\n"); + + if (ret < 0 || ret >= (int)buffer_size) { + PPP_DEBUG_ERROR("Buffer too small for interface list"); + return ERRCODE_FAIL; + } + + // 检查PPP接口状态 + ppp_state_t ppp_state = ppp_get_state(); + if (ppp_state == PPP_STATE_CONNECTED) { + // 获取PPP连接信息 + ppp_connection_info_t network_info; + errcode_t info_ret = ppp_get_connection_info(&network_info); + + // 获取实际的PPP网络接口名称 + char ppp_netif_name[16]; + errcode_t name_ret = ppp_api_get_ppp_netif_name(ppp_netif_name, sizeof(ppp_netif_name)); + if (name_ret != ERRCODE_SUCC) { + strncpy_s(ppp_netif_name, sizeof(ppp_netif_name), "pp0", sizeof(ppp_netif_name) - 1); + } + + int remaining = buffer_size - ret; + if (remaining > 0 && info_ret == ERRCODE_SUCC) { + ret += snprintf(interfaces_info + ret, remaining, + "[1] %s (PPP Interface)\n" + " IP: %u.%u.%u.%u\n" + " Remote: %u.%u.%u.%u\n" + " DNS1: %u.%u.%u.%u\n" + " DNS2: %u.%u.%u.%u\n" + " MTU: %u\n" + " Status: UP CONNECTED\n" + " Type: PPP\n\n", + ppp_netif_name, + (network_info.local_ip >> 0) & 0xFF, + (network_info.local_ip >> 8) & 0xFF, + (network_info.local_ip >> 16) & 0xFF, + (network_info.local_ip >> 24) & 0xFF, + (network_info.remote_ip >> 0) & 0xFF, + (network_info.remote_ip >> 8) & 0xFF, + (network_info.remote_ip >> 16) & 0xFF, + (network_info.remote_ip >> 24) & 0xFF, + (network_info.primary_dns >> 0) & 0xFF, + (network_info.primary_dns >> 8) & 0xFF, + (network_info.primary_dns >> 16) & 0xFF, + (network_info.primary_dns >> 24) & 0xFF, + (network_info.secondary_dns >> 0) & 0xFF, + (network_info.secondary_dns >> 8) & 0xFF, + (network_info.secondary_dns >> 16) & 0xFF, + (network_info.secondary_dns >> 24) & 0xFF, + network_info.mtu); + } + } else { + // 获取实际的PPP网络接口名称 + char ppp_netif_name[16]; + errcode_t name_ret = ppp_api_get_ppp_netif_name(ppp_netif_name, sizeof(ppp_netif_name)); + if (name_ret != ERRCODE_SUCC) { + strncpy_s(ppp_netif_name, sizeof(ppp_netif_name), "pp0", sizeof(ppp_netif_name) - 1); + } + + int remaining = buffer_size - ret; + if (remaining > 0) { + ret += snprintf(interfaces_info + ret, remaining, + "[1] %s (PPP Interface)\n" + " Status: DOWN\n" + " Type: PPP\n\n", + ppp_netif_name); + } + } + + // 添加总结信息 + int remaining = buffer_size - ret; + if (remaining > 0) { + ret += snprintf(interfaces_info + ret, remaining, + "Total interfaces: %d\n" + "Use ppp_api_set_default_netif() to set default interface\n", + (ppp_state == PPP_STATE_CONNECTED) ? 2 : 2); + } + + PPP_DEBUG_INFO("Network interfaces listed successfully"); + return (ret > 0 && ret < (int)buffer_size) ? ERRCODE_SUCC : ERRCODE_FAIL; +} + +/** + * @brief 获取网络接口详细状态信息 + * @param netif_name 网络接口名称 + * @param status_info 输出缓冲区,包含状态信息 + * @param buffer_size 缓冲区大小 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_api_get_netif_status(const char* netif_name, char* status_info, uint32_t buffer_size) +{ + if (netif_name == NULL || status_info == NULL || buffer_size == 0) { + PPP_DEBUG_ERROR("Invalid parameters"); + return ERRCODE_INVALID_PARAM; + } + + PPP_DEBUG_INFO("Getting status for network interface: %s", netif_name); + + // 初始化输出缓冲区 + memset(status_info, 0, buffer_size); + + if (strcmp(netif_name, "lo") == 0) { + // 回环接口状态 + snprintf(status_info, buffer_size, + "=== Interface Status: %s ===\n" + "Name: lo\n" + "Type: Loopback\n" + "IP: 127.0.0.1\n" + "Netmask: 255.0.0.0\n" + "Status: UP\n" + "MTU: 65536\n", netif_name); + } else { + // 检查是否是PPP接口 + // 获取实际的PPP网络接口名称 + char ppp_netif_name[16]; + errcode_t name_ret = ppp_api_get_ppp_netif_name(ppp_netif_name, sizeof(ppp_netif_name)); + bool is_ppp_interface = false; + + if (name_ret == ERRCODE_SUCC && strcmp(netif_name, ppp_netif_name) == 0) { + is_ppp_interface = true; + } else if (strcmp(netif_name, "pp0") == 0) { + // 兼容性:如果用户查询pp0,也认为是PPP接口 + is_ppp_interface = true; + strncpy_s(ppp_netif_name, sizeof(ppp_netif_name), "pp0", sizeof(ppp_netif_name) - 1); + } + + if (is_ppp_interface) { + // PPP接口状态 + ppp_state_t ppp_state = ppp_get_state(); + + if (ppp_state == PPP_STATE_CONNECTED) { + ppp_connection_info_t network_info; + errcode_t ret = ppp_get_connection_info(&network_info); + + if (ret == ERRCODE_SUCC) { + snprintf(status_info, buffer_size, + "=== Interface Status: %s ===\n" + "Name: %s\n" + "Type: PPP\n" + "IP: %u.%u.%u.%u\n" + "Remote: %u.%u.%u.%u\n" + "DNS1: %u.%u.%u.%u\n" + "DNS2: %u.%u.%u.%u\n" + "MTU: %u\n" + "Status: UP CONNECTED\n", + netif_name, ppp_netif_name, + (network_info.local_ip >> 0) & 0xFF, + (network_info.local_ip >> 8) & 0xFF, + (network_info.local_ip >> 16) & 0xFF, + (network_info.local_ip >> 24) & 0xFF, + (network_info.remote_ip >> 0) & 0xFF, + (network_info.remote_ip >> 8) & 0xFF, + (network_info.remote_ip >> 16) & 0xFF, + (network_info.remote_ip >> 24) & 0xFF, + (network_info.primary_dns >> 0) & 0xFF, + (network_info.primary_dns >> 8) & 0xFF, + (network_info.primary_dns >> 16) & 0xFF, + (network_info.primary_dns >> 24) & 0xFF, + (network_info.secondary_dns >> 0) & 0xFF, + (network_info.secondary_dns >> 8) & 0xFF, + (network_info.secondary_dns >> 16) & 0xFF, + (network_info.secondary_dns >> 24) & 0xFF, + network_info.mtu); + } else { + snprintf(status_info, buffer_size, + "=== Interface Status: %s ===\n" + "Name: %s\n" + "Type: PPP\n" + "Status: UP (No network info available)\n", + netif_name, ppp_netif_name); + } + } else { + snprintf(status_info, buffer_size, + "=== Interface Status: %s ===\n" + "Name: %s\n" + "Type: PPP\n" + "Status: DOWN\n", + netif_name, ppp_netif_name); + } + } else { + // 未知接口 + snprintf(status_info, buffer_size, + "=== Interface Status: %s ===\n" + "Error: Interface not found\n" + "Available interfaces: lo, %s\n", + netif_name, + (name_ret == ERRCODE_SUCC) ? ppp_netif_name : "pp0"); + } + } + + PPP_DEBUG_INFO("Interface status retrieved successfully"); + return ERRCODE_SUCC; +} + +/** + * @brief 强制重新协商IPCP以获取IP地址 + * @param result_info 输出缓冲区,包含协商结果信息 + * @param buffer_size 缓冲区大小 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_api_force_ipcp_renegotiation(char* result_info, uint32_t buffer_size) +{ + if (result_info == NULL || buffer_size == 0) { + PPP_DEBUG_ERROR("Invalid parameters"); + return ERRCODE_INVALID_PARAM; + } + + PPP_DEBUG_INFO("Forcing IPCP renegotiation..."); + + // 初始化输出缓冲区 + memset(result_info, 0, buffer_size); + + // 获取PPP网络接口 + struct netif *ppp_netif = ppp_lwip_get_netif(); + if (!ppp_netif) { + snprintf(result_info, buffer_size, "ERROR: PPP netif not available\n"); + PPP_DEBUG_ERROR("PPP netif not available"); + return ERRCODE_FAIL; + } + + // 检查PPP连接状态 + ppp_state_t ppp_state = ppp_get_state(); + if (ppp_state != PPP_STATE_CONNECTED) { + snprintf(result_info, buffer_size, "ERROR: PPP not connected (state: %d)\n", ppp_state); + PPP_DEBUG_ERROR("PPP not connected"); + return ERRCODE_FAIL; + } + + int info_len = snprintf(result_info, buffer_size, + "=== IPCP Renegotiation ===\n" + "PPP State: CONNECTED\n" + "IP Before: %u.%u.%u.%u\n", + (ppp_netif->ip_addr.addr >> 0) & 0xFF, + (ppp_netif->ip_addr.addr >> 8) & 0xFF, + (ppp_netif->ip_addr.addr >> 16) & 0xFF, + (ppp_netif->ip_addr.addr >> 24) & 0xFF); + + if (info_len < 0 || info_len >= (int)buffer_size) { + PPP_DEBUG_ERROR("Buffer too small for result info"); + return ERRCODE_FAIL; + } + + // 强制重新激活网络接口 + PPP_DEBUG_INFO("Forcing netif activation..."); + netif_set_up(ppp_netif); + netif_set_link_up(ppp_netif); + + // 等待IPCP协商完成 + bool ip_acquired = false; + for (int retry = 0; retry < 20; retry++) { + // 等待250ms + osal_msleep(250); + + // 检查IP地址是否已分配 + if (ppp_netif->ip_addr.addr != 0) { + ip_acquired = true; + PPP_DEBUG_INFO("IP address acquired after %d retries", retry + 1); + break; + } + + PPP_DEBUG_INFO("IPCP renegotiation retry %d/20", retry + 1); + + // 每5次重试强制重新激活 + if ((retry + 1) % 5 == 0) { + PPP_DEBUG_INFO("Forcing netif reactivation (retry %d)", retry + 1); + netif_set_up(ppp_netif); + netif_set_link_up(ppp_netif); + } + } + + // 生成结果信息 + int remaining = buffer_size - info_len; + if (remaining > 0) { + if (ip_acquired) { + info_len += snprintf(result_info + info_len, remaining, + "IP After: %u.%u.%u.%u\n" + "Gateway: %u.%u.%u.%u\n" + "Netmask: %u.%u.%u.%u\n" + "Flags: 0x%02x\n" + "Status: SUCCESS - IP address acquired\n", + (ppp_netif->ip_addr.addr >> 0) & 0xFF, + (ppp_netif->ip_addr.addr >> 8) & 0xFF, + (ppp_netif->ip_addr.addr >> 16) & 0xFF, + (ppp_netif->ip_addr.addr >> 24) & 0xFF, + (ppp_netif->gw.addr >> 0) & 0xFF, + (ppp_netif->gw.addr >> 8) & 0xFF, + (ppp_netif->gw.addr >> 16) & 0xFF, + (ppp_netif->gw.addr >> 24) & 0xFF, + (ppp_netif->netmask.addr >> 0) & 0xFF, + (ppp_netif->netmask.addr >> 8) & 0xFF, + (ppp_netif->netmask.addr >> 16) & 0xFF, + (ppp_netif->netmask.addr >> 24) & 0xFF, + ppp_netif->flags); + + // 设置为默认网络接口 + netif_set_default(ppp_netif); + + remaining = buffer_size - info_len; + if (remaining > 50) { + snprintf(result_info + info_len, remaining, "\nSet as default network interface\n"); + } + } else { + snprintf(result_info + info_len, remaining, + "IP After: 0.0.0.0 (FAILED)\n" + "Status: FAILED - IPCP negotiation timeout\n" + "Suggestion: Check network provider settings\n"); + } + } + + PPP_DEBUG_INFO("IPCP renegotiation %s", ip_acquired ? "succeeded" : "failed"); + return ip_acquired ? ERRCODE_SUCC : ERRCODE_FAIL; +} \ No newline at end of file diff --git a/code/sdk/zhihui/ppp/src/ppp_at_handler.c b/code/sdk/zhihui/ppp/src/ppp_at_handler.c index a3acb2221..854101c87 100644 --- a/code/sdk/zhihui/ppp/src/ppp_at_handler.c +++ b/code/sdk/zhihui/ppp/src/ppp_at_handler.c @@ -421,20 +421,48 @@ ppp_error_t ppp_at_complete_dial_sequence(const char *apn) } PPP_DEBUG_INFO("AT handshake successful"); + // 2.5. 禁用回显以防止PPP数据被回显 - 强制执行 + ret = ppp_at_send_command("ATE0", "OK", 5000, &response); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("Failed to disable echo - this is critical for PPP"); + return ret; // 改为致命错误,必须成功 + } else { + PPP_DEBUG_INFO("Echo disabled successfully"); + } + + // 移除ATQ0和ATV1命令,因为它们在某些调制解调器上不被支持 + // 且对PPP连接不是必需的 + // 3. 设置固定波特率 (AT+IPR=2000000,掉电保持) // 获取当前波特率并设置为固定波特率 uint32_t current_baudrate = ppp_at_get_current_baudrate(); if (current_baudrate > 0) { PPP_DEBUG_INFO("Setting fixed baudrate to %u (power-off persistent)", current_baudrate); - ret = ppp_at_send_command("AT+IPR=2000000", "OK", 5000, &response); + + char ipr_cmd[32]; + snprintf_s(ipr_cmd, sizeof(ipr_cmd), sizeof(ipr_cmd) - 1, "AT+IPR=%u", current_baudrate); + + ret = ppp_at_send_command(ipr_cmd, "OK", 5000, &response); if (ret != PPP_ERR_OK) { - PPP_DEBUG_WARN("Failed to set fixed baudrate AT+IPR=2000000, continuing with current rate"); - // 不作为致命错误,继续执行 + PPP_DEBUG_WARN("Failed to set fixed baudrate %s, continuing with current rate", ipr_cmd); + // 不返回错误,继续执行 } else { - PPP_DEBUG_INFO("Fixed baudrate 2000000 set successfully (power-off persistent)"); - // 注意:这里不立即更改串口波特率,因为模块需要时间应用设置 - // 下次开机时模块将自动使用2M波特率 + PPP_DEBUG_INFO("Fixed baudrate set successfully"); } + } else { + PPP_DEBUG_WARN("Could not determine current baudrate, skipping AT+IPR"); + } + + // 3.5. 确保调制解调器完全退出AT命令模式 + PPP_DEBUG_INFO("Ensuring modem is ready for PPP data mode..."); + + // 发送一个简单的AT命令确认调制解调器状态 + ret = ppp_at_send_command("AT", "OK", 3000, &response); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("Modem not responding to AT - may already be in data mode"); + // 这可能是正常的,如果调制解调器已经在数据模式 + } else { + PPP_DEBUG_INFO("Modem still in AT mode, proceeding with dial sequence"); } // 4. 设置PDP上下文 (对应chat文件: OK 'AT+CGDCONT=3,"IP"') @@ -454,14 +482,86 @@ ppp_error_t ppp_at_complete_dial_sequence(const char *apn) } PPP_DEBUG_INFO("PDP context set successfully"); + // 4.5. 设置网络注册模式(确保网络连接稳定) + ret = ppp_at_send_command("AT+CREG=1", "OK", 5000, &response); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_WARN("Failed to set network registration mode, continuing anyway"); + } else { + PPP_DEBUG_INFO("Network registration mode set successfully"); + } + + // 4.6. 设置GPRS附着模式 + ret = ppp_at_send_command("AT+CGATT=1", "OK", 10000, &response); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_WARN("Failed to attach to GPRS, continuing anyway"); + } else { + PPP_DEBUG_INFO("GPRS attach successful"); + } + + // 4.7. 检查网络状态 + ret = ppp_at_send_command("AT+CREG?", "OK", 5000, &response); + if (ret == PPP_ERR_OK) { + PPP_DEBUG_INFO("Network registration status: %s", response.response); + } + // 5. 发送PPP拨号指令 (对应chat文件: OK 'ATD*99***2#' -> CONNECTED) ret = ppp_at_send_command("ATD*99***2#", "CONNECT", 30000, &response); if (ret != PPP_ERR_OK) { - PPP_DEBUG_ERROR("PPP dial failed"); + PPP_DEBUG_ERROR("PPP dial command failed"); return ret; } - PPP_DEBUG_INFO("PPP dial sequence completed successfully - entering data mode"); + + // 6.5. 关键修复:确保调制解调器完全进入数据模式 + PPP_DEBUG_INFO("Ensuring modem is fully in PPP data mode..."); + + // 等待调制解调器稳定 + osal_msleep(1000); + + // 发送一个空的AT命令来测试是否还在AT模式 + // 如果还在AT模式,会有响应;如果在PPP模式,不会有响应 + uint8_t test_cmd[] = "AT\r\n"; + uint32_t bytes_written = 0; + ppp_error_t test_ret = ppp_serial_write(test_cmd, sizeof(test_cmd)-1, &bytes_written); + + if (test_ret == PPP_ERR_OK) { + // 等待可能的AT响应 + osal_msleep(500); + + uint8_t response_buffer[64]; + uint32_t bytes_read = 0; + ppp_error_t read_ret = ppp_serial_read(response_buffer, sizeof(response_buffer), &bytes_read); + + if (read_ret == PPP_ERR_OK && bytes_read > 0) { + PPP_DEBUG_WARN("Modem still responding to AT commands after CONNECT!"); + PPP_DEBUG_WARN("Received %u bytes: %.*s", bytes_read, bytes_read, response_buffer); + + // 尝试强制进入数据模式 + PPP_DEBUG_INFO("Forcing modem into data mode..."); + + // 发送ATE0再次确保回显关闭 + uint8_t ate0_cmd[] = "ATE0\r\n"; + ppp_serial_write(ate0_cmd, sizeof(ate0_cmd)-1, &bytes_written); + osal_msleep(500); + + // 清理任何响应 + ppp_serial_read(response_buffer, sizeof(response_buffer), &bytes_read); + + // 再次拨号 + PPP_DEBUG_INFO("Re-dialing to ensure proper PPP mode..."); + ret = ppp_at_send_command("ATD*99***2#", "CONNECT", 30000, &response); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("Re-dial failed"); + return ret; + } + + osal_msleep(2000); // 更长的等待时间 + } else { + PPP_DEBUG_INFO("Modem correctly in PPP data mode - no AT response"); + } + } + + PPP_DEBUG_INFO("Modem data mode verification completed"); return PPP_ERR_OK; } diff --git a/code/sdk/zhihui/ppp/src/ppp_cat1_api.c b/code/sdk/zhihui/ppp/src/ppp_cat1_api.c index 5f529f3f3..29a21d101 100644 --- a/code/sdk/zhihui/ppp/src/ppp_cat1_api.c +++ b/code/sdk/zhihui/ppp/src/ppp_cat1_api.c @@ -79,9 +79,9 @@ typedef struct { int sim; int signal; char opera[64]; - char imei[20]; - char pyVer[20]; - char iccid[20]; + char imei[32]; + char pyVer[32]; + char iccid[32]; char modemVer[64]; } ppp_cat1_runtime_status_t; diff --git a/code/sdk/zhihui/ppp/src/ppp_lwip.c b/code/sdk/zhihui/ppp/src/ppp_lwip.c index 521d9e4dc..97aca6a93 100644 --- a/code/sdk/zhihui/ppp/src/ppp_lwip.c +++ b/code/sdk/zhihui/ppp/src/ppp_lwip.c @@ -60,6 +60,13 @@ ppp_error_t ppp_lwip_init(const ppp_lwip_config_t *config) PPP_DEBUG_INFO("Initializing PPP lwIP integration"); + /* 重置连接状态 */ + g_lwip_ctx.connected = false; + g_lwip_ctx.local_ip = 0; + g_lwip_ctx.remote_ip = 0; + g_lwip_ctx.primary_dns = 0; + g_lwip_ctx.secondary_dns = 0; + /* 分配网络接口 */ g_lwip_ctx.netif = (struct netif *)osal_kmalloc(sizeof(struct netif)); if (!g_lwip_ctx.netif) { @@ -85,11 +92,45 @@ ppp_error_t ppp_lwip_init(const ppp_lwip_config_t *config) if (config->username && config->password) { ppp_set_auth(g_lwip_ctx.ppp_pcb, PPPAUTHTYPE_PAP, config->username, config->password); PPP_DEBUG_INFO("PPP authentication configured (PAP)"); + } else { + /* 如果没有用户名密码,设置为无认证 */ + ppp_set_auth(g_lwip_ctx.ppp_pcb, PPPAUTHTYPE_NONE, "", ""); + PPP_DEBUG_INFO("PPP authentication disabled (NONE)"); } + /* 配置IPCP选项 - 启用IP地址协商 */ + PPP_DEBUG_INFO("Configuring IPCP options..."); + + /* 请求对端分配IP地址 (0.0.0.0表示请求分配) */ + ppp_set_ipcp_ouraddr(g_lwip_ctx.ppp_pcb, IP4_ADDR_ANY); + + /* 接受对端提供的任何IP地址 */ + ppp_set_ipcp_hisaddr(g_lwip_ctx.ppp_pcb, IP4_ADDR_ANY); + + /* 启用DNS协商 */ + ppp_set_usepeerdns(g_lwip_ctx.ppp_pcb, 1); + + /* 使用标准IPCP协商选项 */ + PPP_DEBUG_INFO("Setting standard IPCP negotiation options..."); + + /* 启用基本的IP地址协商 */ + g_lwip_ctx.ppp_pcb->ipcp_wantoptions.neg_addr = 1; + g_lwip_ctx.ppp_pcb->ipcp_allowoptions.neg_addr = 1; + +#if LWIP_DNS + /* 请求DNS服务器地址 */ + g_lwip_ctx.ppp_pcb->ipcp_wantoptions.req_dns1 = 1; + g_lwip_ctx.ppp_pcb->ipcp_wantoptions.req_dns2 = 1; +#endif + + PPP_DEBUG_INFO("IPCP configuration completed with standard options"); + /* 设置状态回调 */ ppp_set_notify_phase_callback(g_lwip_ctx.ppp_pcb, ppp_lwip_status_callback); + /* 使用标准PPP/LCP配置 */ + PPP_DEBUG_INFO("Using standard PPP/LCP configuration..."); + /* 保存回调函数 */ g_lwip_ctx.event_callback = config->event_callback; g_lwip_ctx.event_callback_arg = config->event_callback_arg; @@ -144,39 +185,36 @@ ppp_error_t ppp_lwip_connect(void) return PPP_ERR_INVALID_PARAM; #else if (!g_lwip_ctx.initialized) { + PPP_DEBUG_ERROR("PPP lwIP not initialized"); return PPP_ERR_INVALID_PARAM; } + /* 注释掉"already connected"检查,允许重新连接 */ if (g_lwip_ctx.connected) { - PPP_DEBUG_WARN("PPP already connected"); - return PPP_ERR_OK; + PPP_DEBUG_WARN("PPP was previously connected, will restart negotiation"); + g_lwip_ctx.connected = false; /* 重置连接状态 */ } - PPP_DEBUG_INFO("Connecting PPP using custom serial interface"); - - /* 创建PPPoS连接,使用自定义输出回调 */ - g_lwip_ctx.ppp_pcb = pppos_create(&g_lwip_ctx.netif, - ppp_lwip_output_callback, // 自定义输出回调 - ppp_lwip_status_callback, - &g_lwip_ctx); - if (g_lwip_ctx.ppp_pcb == NULL) { - PPP_DEBUG_ERROR("Failed to create PPPoS connection"); - return PPP_ERR_MEMORY; + if (!g_lwip_ctx.ppp_pcb) { + PPP_DEBUG_ERROR("PPP control block not available"); + return PPP_ERR_INVALID_PARAM; } - /* 设置认证信息 */ - ppp_set_auth(g_lwip_ctx.ppp_pcb, PPPAUTHTYPE_NONE, "", ""); + PPP_DEBUG_PRINT("=== Starting PPP Protocol Negotiation ===\n"); + PPP_DEBUG_PRINT("Initiating PPP connection with lwIP...\n"); + PPP_DEBUG_PRINT("This will trigger LCP and IPCP negotiation\n"); /* 启动PPP连接 */ err_t err = ppp_connect(g_lwip_ctx.ppp_pcb, 0); if (err != ERR_OK) { PPP_DEBUG_ERROR("Failed to start PPP connection: %d", err); - ppp_free(g_lwip_ctx.ppp_pcb); - g_lwip_ctx.ppp_pcb = NULL; + PPP_DEBUG_PRINT("=== PPP Connection FAILED ===\n"); return PPP_ERR_DIAL_FAILED; } - PPP_DEBUG_INFO("PPP connection initiated with custom serial interface"); + PPP_DEBUG_PRINT("PPP connection initiated successfully\n"); + PPP_DEBUG_PRINT("Watch for PPP Protocol Output/Input logs below...\n"); + PPP_DEBUG_PRINT("=== PPP Negotiation Started ===\n"); return PPP_ERR_OK; #endif } @@ -212,7 +250,8 @@ ppp_error_t ppp_lwip_disconnect(void) return PPP_ERR_OK; #endif } - +static const char* ppp_get_lcp_code_name(uint8_t code); +static const char* ppp_get_protocol_name(uint16_t protocol); /** * @brief 输入PPP数据 */ @@ -225,12 +264,89 @@ ppp_error_t ppp_lwip_input(const uint8_t *data, uint32_t length) return PPP_ERR_INVALID_PARAM; } - PPP_DEBUG_DEBUG("PPP input %u bytes", length); - PPP_DEBUG_HEXDUMP(data, length); + PPP_DEBUG_PRINT("=== PPP Protocol Input ===\n"); + PPP_DEBUG_PRINT("PPP RX: %u bytes\n", length); + + /* 解析PPP协议包 */ + if (length >= 4) { + /* 跳过PPP Flag (0x7E) 如果存在 */ + uint32_t offset = 0; + if (data[0] == 0x7E) { + offset = 1; + } + + /* 检查Address/Control字段 */ + if (offset + 3 < length && data[offset] == 0xFF && data[offset + 1] == 0x03) { + offset += 2; /* 跳过Address/Control */ + + /* 解析协议字段 */ + if (offset + 1 < length) { + uint16_t protocol = (data[offset] << 8) | data[offset + 1]; + offset += 2; + + PPP_DEBUG_PRINT("Protocol: 0x%04X (%s)\n", protocol, ppp_get_protocol_name(protocol)); + + /* 解析LCP/IPCP包 */ + if ((protocol == 0xC021 || protocol == 0x8021) && offset + 3 < length) { + uint8_t code = data[offset]; + uint8_t id = data[offset + 1]; + uint16_t pkt_length = (data[offset + 2] << 8) | data[offset + 3]; + + PPP_DEBUG_PRINT(" Code: %u (%s)\n", code, ppp_get_lcp_code_name(code)); + PPP_DEBUG_PRINT(" ID: %u\n", id); + PPP_DEBUG_PRINT(" Length: %u\n", pkt_length); + + /* 解析Configure-Request/Ack/Nak的选项 */ + if ((code >= 1 && code <= 4) && offset + 4 < length) { /* Configure packets */ + uint32_t opt_offset = offset + 4; + PPP_DEBUG_PRINT(" Options:\n"); + + while (opt_offset + 1 < length && opt_offset < offset + pkt_length) { + uint8_t opt_type = data[opt_offset]; + uint8_t opt_len = data[opt_offset + 1]; + + if (opt_len < 2 || opt_offset + opt_len > length) break; + + PPP_DEBUG_PRINT(" Type: %u, Length: %u", opt_type, opt_len); + + /* 解析常见选项 */ + if (protocol == 0x8021 && opt_type == 3 && opt_len == 6) { /* IPCP IP Address */ + PPP_DEBUG_PRINT(" (IP Address: %u.%u.%u.%u)", + data[opt_offset + 2], data[opt_offset + 3], + data[opt_offset + 4], data[opt_offset + 5]); + } else if (protocol == 0x8021 && opt_type == 129 && opt_len == 6) { /* Primary DNS */ + PPP_DEBUG_PRINT(" (Primary DNS: %u.%u.%u.%u)", + data[opt_offset + 2], data[opt_offset + 3], + data[opt_offset + 4], data[opt_offset + 5]); + } else if (protocol == 0x8021 && opt_type == 131 && opt_len == 6) { /* Secondary DNS */ + PPP_DEBUG_PRINT(" (Secondary DNS: %u.%u.%u.%u)", + data[opt_offset + 2], data[opt_offset + 3], + data[opt_offset + 4], data[opt_offset + 5]); + } + + PPP_DEBUG_PRINT("\n"); + opt_offset += opt_len; + } + } + } + } + } + } + + /* 打印原始数据 */ + PPP_DEBUG_PRINT("Raw Data: "); + for (uint32_t i = 0; i < length && i < 32; i++) { + PPP_DEBUG_PRINT("%02X ", data[i]); + } + if (length > 32) { + PPP_DEBUG_PRINT("... (total %u bytes)", length); + } + PPP_DEBUG_PRINT("\n"); /* 将数据传递给PPPoS */ pppos_input(g_lwip_ctx.ppp_pcb, (u8_t *)data, length); + PPP_DEBUG_PRINT("=== PPP Input Processed ===\n"); return PPP_ERR_OK; #endif } @@ -291,6 +407,26 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx) (void)ctx; PPP_DEBUG_INFO("PPP status callback: err_code=%d", err_code); + + /* 打印PPP阶段信息 */ + const char* phase_str = "UNKNOWN"; + switch (err_code) { + case PPPERR_NONE: phase_str = "CONNECTED"; break; + case PPPERR_PARAM: phase_str = "PARAM_ERROR"; break; + case PPPERR_OPEN: phase_str = "OPEN_ERROR"; break; + case PPPERR_DEVICE: phase_str = "DEVICE_ERROR"; break; + case PPPERR_ALLOC: phase_str = "ALLOC_ERROR"; break; + case PPPERR_USER: phase_str = "USER_ERROR"; break; + case PPPERR_CONNECT: phase_str = "CONNECT_ERROR"; break; + case PPPERR_AUTHFAIL: phase_str = "AUTH_FAIL"; break; + case PPPERR_PROTOCOL: phase_str = "PROTOCOL_ERROR"; break; + case PPPERR_PEERDEAD: phase_str = "PEER_DEAD"; break; + case PPPERR_IDLETIMEOUT: phase_str = "IDLE_TIMEOUT"; break; + case PPPERR_CONNECTTIME: phase_str = "CONNECT_TIMEOUT"; break; + case PPPERR_LOOPBACK: phase_str = "LOOPBACK"; break; + default: phase_str = "OTHER"; break; + } + PPP_DEBUG_INFO("PPP Phase: %s (%d)", phase_str, err_code); ppp_lwip_event_t event; memset_s(&event, sizeof(event), 0, sizeof(event)); @@ -303,6 +439,12 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx) /* 获取IP地址信息 */ if (g_lwip_ctx.netif) { + PPP_DEBUG_INFO("PPP netif available, checking IP addresses..."); + PPP_DEBUG_INFO("netif->ip_addr: 0x%08x", ip4_addr_get_u32(&g_lwip_ctx.netif->ip_addr)); + PPP_DEBUG_INFO("netif->gw: 0x%08x", ip4_addr_get_u32(&g_lwip_ctx.netif->gw)); + PPP_DEBUG_INFO("netif->netmask: 0x%08x", ip4_addr_get_u32(&g_lwip_ctx.netif->netmask)); + PPP_DEBUG_INFO("netif flags: 0x%02x", g_lwip_ctx.netif->flags); + g_lwip_ctx.local_ip = ip4_addr_get_u32(&g_lwip_ctx.netif->ip_addr); g_lwip_ctx.remote_ip = ip4_addr_get_u32(&g_lwip_ctx.netif->gw); @@ -311,9 +453,11 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx) const ip_addr_t *dns2 = dns_getserver(1); if (dns1) { g_lwip_ctx.primary_dns = ip4_addr_get_u32(ip_2_ip4(dns1)); + PPP_DEBUG_INFO("DNS1: 0x%08x", g_lwip_ctx.primary_dns); } if (dns2) { g_lwip_ctx.secondary_dns = ip4_addr_get_u32(ip_2_ip4(dns2)); + PPP_DEBUG_INFO("DNS2: 0x%08x", g_lwip_ctx.secondary_dns); } PPP_DEBUG_INFO("PPP connected - Local IP: %u.%u.%u.%u", @@ -321,6 +465,64 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx) (g_lwip_ctx.local_ip >> 8) & 0xFF, (g_lwip_ctx.local_ip >> 16) & 0xFF, (g_lwip_ctx.local_ip >> 24) & 0xFF); + PPP_DEBUG_INFO("PPP connected - Remote IP: %u.%u.%u.%u", + (g_lwip_ctx.remote_ip >> 0) & 0xFF, + (g_lwip_ctx.remote_ip >> 8) & 0xFF, + (g_lwip_ctx.remote_ip >> 16) & 0xFF, + (g_lwip_ctx.remote_ip >> 24) & 0xFF); + + /* 设置PPP接口为默认网络接口 */ + if (g_lwip_ctx.netif->ip_addr.addr != 0) { + PPP_DEBUG_INFO("Setting PPP interface as default..."); + netif_set_default(g_lwip_ctx.netif); + PPP_DEBUG_INFO("PPP interface set as default network interface"); + } else { + PPP_DEBUG_WARN("PPP IP address is 0, IPCP negotiation may not be complete yet"); + PPP_DEBUG_INFO("Attempting to force IPCP completion..."); + + /* 强制激活网络接口 */ + netif_set_up(g_lwip_ctx.netif); + netif_set_link_up(g_lwip_ctx.netif); + + /* 等待IPCP协商完成的重试机制 */ + for (int retry = 0; retry < 10; retry++) { + /* 等待500ms */ + osal_msleep(500); + + /* 检查IP地址是否已分配 */ + if (g_lwip_ctx.netif->ip_addr.addr != 0) { + PPP_DEBUG_INFO("IPCP negotiation completed after %d retries", retry + 1); + PPP_DEBUG_INFO("Final IP: %u.%u.%u.%u", + (g_lwip_ctx.netif->ip_addr.addr >> 0) & 0xFF, + (g_lwip_ctx.netif->ip_addr.addr >> 8) & 0xFF, + (g_lwip_ctx.netif->ip_addr.addr >> 16) & 0xFF, + (g_lwip_ctx.netif->ip_addr.addr >> 24) & 0xFF); + + /* 更新本地IP地址 */ + g_lwip_ctx.local_ip = ip4_addr_get_u32(&g_lwip_ctx.netif->ip_addr); + + /* 设置为默认网络接口 */ + netif_set_default(g_lwip_ctx.netif); + PPP_DEBUG_INFO("PPP interface set as default network interface"); + break; + } + + PPP_DEBUG_INFO("IPCP retry %d/10 - IP still 0.0.0.0", retry + 1); + + /* 强制重新激活 */ + if (retry == 5) { + PPP_DEBUG_INFO("Mid-retry: forcing netif up again"); + netif_set_up(g_lwip_ctx.netif); + netif_set_link_up(g_lwip_ctx.netif); + } + } + + if (g_lwip_ctx.netif->ip_addr.addr == 0) { + PPP_DEBUG_ERROR("IPCP negotiation failed after 10 retries - IP still 0.0.0.0"); + } + } + } else { + PPP_DEBUG_ERROR("PPP netif is NULL!"); } break; @@ -367,7 +569,20 @@ static void ppp_lwip_link_status_callback(ppp_pcb *pcb, int err_code, void *ctx) PPP_DEBUG_INFO("PPP link status callback: err_code=%d", err_code); if (err_code == PPPERR_NONE) { - PPP_DEBUG_INFO("PPP link up"); + PPP_DEBUG_INFO("PPP link up - checking IPCP status..."); + + // 检查网络接口状态 + if (g_lwip_ctx.netif) { + PPP_DEBUG_INFO("Link up - netif flags: 0x%02x", g_lwip_ctx.netif->flags); + PPP_DEBUG_INFO("Link up - IP: 0x%08x", ip4_addr_get_u32(&g_lwip_ctx.netif->ip_addr)); + + // 如果IP地址还是0,强制激活接口 + if (g_lwip_ctx.netif->ip_addr.addr == 0) { + PPP_DEBUG_WARN("IP still 0 after link up, forcing netif activation"); + netif_set_up(g_lwip_ctx.netif); + netif_set_link_up(g_lwip_ctx.netif); + } + } } else { PPP_DEBUG_WARN("PPP link down: %d", err_code); g_lwip_ctx.connected = false; @@ -383,6 +598,39 @@ static void ppp_lwip_link_status_callback(ppp_pcb *pcb, int err_code, void *ctx) } } +/* PPP协议解析辅助函数 */ +static const char* ppp_get_protocol_name(uint16_t protocol) +{ + switch (protocol) { + case 0xC021: return "LCP"; + case 0x8021: return "IPCP"; + case 0xC023: return "PAP"; + case 0xC223: return "CHAP"; + case 0x0021: return "IP"; + case 0x002D: return "VJ_COMP_TCP"; + case 0x002F: return "VJ_UNCOMP_TCP"; + default: return "UNKNOWN"; + } +} + +static const char* ppp_get_lcp_code_name(uint8_t code) +{ + switch (code) { + case 1: return "Configure-Request"; + case 2: return "Configure-Ack"; + case 3: return "Configure-Nak"; + case 4: return "Configure-Reject"; + case 5: return "Terminate-Request"; + case 6: return "Terminate-Ack"; + case 7: return "Code-Reject"; + case 8: return "Protocol-Reject"; + case 9: return "Echo-Request"; + case 10: return "Echo-Reply"; + case 11: return "Discard-Request"; + default: return "Unknown"; + } +} + /** * @brief PPP输出回调函数 - 使用自定义串口接口,不依赖SIO */ @@ -391,16 +639,94 @@ static u32_t ppp_lwip_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void (void)pcb; (void)ctx; - PPP_DEBUG_DEBUG("PPP output %u bytes", len); - PPP_DEBUG_HEXDUMP(data, len); + PPP_DEBUG_PRINT("=== PPP Protocol Output ===\n"); + PPP_DEBUG_PRINT("PPP TX: %u bytes\n", len); + + /* 解析PPP协议包 */ + if (len >= 4) { + /* 跳过PPP Flag (0x7E) 如果存在 */ + uint32_t offset = 0; + if (data[0] == 0x7E) { + offset = 1; + } + + /* 检查Address/Control字段 */ + if (offset + 3 < len && data[offset] == 0xFF && data[offset + 1] == 0x03) { + offset += 2; /* 跳过Address/Control */ + + /* 解析协议字段 */ + if (offset + 1 < len) { + uint16_t protocol = (data[offset] << 8) | data[offset + 1]; + offset += 2; + + PPP_DEBUG_PRINT("Protocol: 0x%04X (%s)\n", protocol, ppp_get_protocol_name(protocol)); + + /* 解析LCP/IPCP包 */ + if ((protocol == 0xC021 || protocol == 0x8021) && offset + 3 < len) { + uint8_t code = data[offset]; + uint8_t id = data[offset + 1]; + uint16_t length = (data[offset + 2] << 8) | data[offset + 3]; + + PPP_DEBUG_PRINT(" Code: %u (%s)\n", code, ppp_get_lcp_code_name(code)); + PPP_DEBUG_PRINT(" ID: %u\n", id); + PPP_DEBUG_PRINT(" Length: %u\n", length); + + /* 解析Configure-Request的选项 */ + if (code == 1 && offset + 4 < len) { /* Configure-Request */ + uint32_t opt_offset = offset + 4; + PPP_DEBUG_PRINT(" Options:\n"); + + while (opt_offset + 1 < len && opt_offset < offset + length) { + uint8_t opt_type = data[opt_offset]; + uint8_t opt_len = data[opt_offset + 1]; + + if (opt_len < 2 || opt_offset + opt_len > len) break; + + PPP_DEBUG_PRINT(" Type: %u, Length: %u", opt_type, opt_len); + + /* 解析常见选项 */ + if (protocol == 0x8021 && opt_type == 3 && opt_len == 6) { /* IPCP IP Address */ + PPP_DEBUG_PRINT(" (IP Address: %u.%u.%u.%u)", + data[opt_offset + 2], data[opt_offset + 3], + data[opt_offset + 4], data[opt_offset + 5]); + } else if (protocol == 0x8021 && opt_type == 129 && opt_len == 6) { /* Primary DNS */ + PPP_DEBUG_PRINT(" (Primary DNS: %u.%u.%u.%u)", + data[opt_offset + 2], data[opt_offset + 3], + data[opt_offset + 4], data[opt_offset + 5]); + } else if (protocol == 0x8021 && opt_type == 131 && opt_len == 6) { /* Secondary DNS */ + PPP_DEBUG_PRINT(" (Secondary DNS: %u.%u.%u.%u)", + data[opt_offset + 2], data[opt_offset + 3], + data[opt_offset + 4], data[opt_offset + 5]); + } + + PPP_DEBUG_PRINT("\n"); + opt_offset += opt_len; + } + } + } + } + } + } + + /* 打印原始数据 */ + PPP_DEBUG_PRINT("Raw Data: "); + for (uint32_t i = 0; i < len && i < 32; i++) { + PPP_DEBUG_PRINT("%02X ", data[i]); + } + if (len > 32) { + PPP_DEBUG_PRINT("... (total %u bytes)", len); + } + PPP_DEBUG_PRINT("\n"); /* 直接使用我们自己的串口写函数,不依赖SIO */ ppp_error_t ret = ppp_serial_write(data, len); if (ret != PPP_ERR_OK) { PPP_DEBUG_ERROR("Failed to send PPP data via custom serial: %d", ret); + PPP_DEBUG_PRINT("=== PPP Output FAILED ===\n"); return 0; } + PPP_DEBUG_PRINT("=== PPP Output SUCCESS ===\n"); return len; } #endif /* LWIP_PPP_SUPPORT */ \ No newline at end of file diff --git a/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c b/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c new file mode 100644 index 000000000..116151e9d --- /dev/null +++ b/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c @@ -0,0 +1,202 @@ +/** + * @file ppp_lwip_thread.c + * @brief PPP接收线程实现 - 参考lwIP slipif_init方式 + */ + +#include "ppp_api.h" +#include "ppp_config.h" +#include "ppp_debug.h" +#include "ppp_serial.h" +#include "ppp_lwip.h" +#include "soc_osal.h" +#include "schedule/osal_task.h" +#include +#include + +/* PPP接收线程相关 - 参考slipif_init方式 */ +static osal_task *g_ppp_rx_thread = NULL; +static volatile bool g_ppp_rx_thread_running = false; + +/** + * @brief PPP数据接收线程 - 参考slipif_init实现 + * + * 这个实现参考了lwIP中slipif_init的线程创建方式: + * 1. 使用标准的线程函数签名 + * 2. 实现流数据处理和PPP帧重组 + * 3. 直接调用lwIP的输入函数 + */ +static void ppp_lwip_receive_thread(void *arg) +{ + (void)arg; + + PPP_DEBUG_INFO("PPP lwIP receive thread started (slipif-style)"); + + /* 动态分配接收缓冲区以避免栈溢出 */ + uint8_t *rx_buffer = (uint8_t *)malloc(PPP_RX_BUFFER_SIZE); + if (!rx_buffer) { + PPP_DEBUG_ERROR("Failed to allocate RX buffer for PPP thread"); + return; + } + + /* 动态分配PPP流处理缓冲区 */ + uint8_t *stream_buffer = (uint8_t *)malloc(PPP_RX_BUFFER_SIZE * 2); + if (!stream_buffer) { + PPP_DEBUG_ERROR("Failed to allocate stream buffer for PPP thread"); + free(rx_buffer); + return; + } + + uint32_t bytes_read; + uint32_t total_packets = 0; + uint32_t total_bytes = 0; + + /* PPP流处理状态 */ + uint32_t stream_pos = 0; /* 流缓冲区当前位置 */ + bool in_frame = false; /* 是否正在接收PPP帧 */ + uint32_t frame_start = 0; /* 当前帧开始位置 */ + uint32_t complete_frames = 0; /* 完整帧计数 */ + + PPP_DEBUG_INFO("PPP lwIP thread: allocated %d bytes RX buffer + %d bytes stream buffer", + PPP_RX_BUFFER_SIZE, PPP_RX_BUFFER_SIZE * 2); + + /* 主接收循环 - 参考slipif的实现方式 */ + while (g_ppp_rx_thread_running) { + // 从串口读取PPP数据 + ppp_error_t ret = ppp_serial_read(rx_buffer, PPP_RX_BUFFER_SIZE, &bytes_read); + + if (ret == PPP_ERR_OK && bytes_read > 0) { + total_packets++; + total_bytes += bytes_read; + + PPP_DEBUG_DEBUG("PPP lwIP RX: Fragment #%u, %u bytes", total_packets, bytes_read); + + // 将新数据添加到流缓冲区 + if (stream_pos + bytes_read < PPP_RX_BUFFER_SIZE * 2) { + memcpy(stream_buffer + stream_pos, rx_buffer, bytes_read); + stream_pos += bytes_read; + + // 处理流缓冲区中的数据,查找完整的PPP帧 + uint32_t processed = 0; + while (processed < stream_pos) { + uint8_t byte = stream_buffer[processed]; + + if (byte == 0x7E) { /* PPP帧标志 */ + if (in_frame && processed > frame_start) { + /* 找到完整帧的结束 */ + uint32_t frame_len = processed - frame_start + 1; + complete_frames++; + + PPP_DEBUG_DEBUG("PPP lwIP Complete Frame #%u: %u bytes", + complete_frames, frame_len); + + // 将完整帧传递给lwIP PPP协议栈 + ppp_error_t input_ret = ppp_lwip_input(stream_buffer + frame_start, frame_len); + if (input_ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("Failed to input PPP frame to lwIP: %d", input_ret); + } + } + + /* 开始新帧 */ + frame_start = processed; + in_frame = true; + } + + processed++; + } + + // 如果有未完成的帧,将其移到缓冲区开头 + if (in_frame && frame_start > 0) { + uint32_t remaining = stream_pos - frame_start; + memmove(stream_buffer, stream_buffer + frame_start, remaining); + stream_pos = remaining; + frame_start = 0; + } else if (!in_frame) { + // 没有正在处理的帧,清空缓冲区 + stream_pos = 0; + frame_start = 0; + } + } else { + PPP_DEBUG_WARN("Stream buffer overflow, resetting"); + stream_pos = 0; + frame_start = 0; + in_frame = false; + } + } else if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("PPP serial read error: %d", ret); + } + + // 统计信息输出 - 每2000次循环输出一次 + if ((total_packets % 2000) == 0 && total_packets > 0) { + PPP_DEBUG_INFO("PPP lwIP RX: %u fragments, %u complete frames, %u total bytes", + total_packets, complete_frames, total_bytes); + } + + // 短暂休眠以避免CPU占用过高 - 参考slipif的做法 + osal_msleep(10); + } + + /* 清理资源 */ + free(rx_buffer); + free(stream_buffer); + + PPP_DEBUG_INFO("PPP lwIP receive thread terminated (processed %u frames)", complete_frames); +} + +/** + * @brief 启动PPP接收线程 - 参考slipif_init方式 + */ +ppp_error_t ppp_lwip_start_receive_thread(void) +{ + if (g_ppp_rx_thread != NULL) { + PPP_DEBUG_WARN("PPP lwIP receive thread already running"); + return PPP_ERR_OK; + } + + g_ppp_rx_thread_running = true; + + // 创建PPP数据接收线程 - 参考slipif_init方式 + // slipif使用sys_thread_new,我们使用等效的osal_kthread_create + g_ppp_rx_thread = osal_kthread_create((osal_kthread_handler)ppp_lwip_receive_thread, + NULL, "ppp_lwip_rx", PPP_RX_THREAD_STACK_SIZE); + if (g_ppp_rx_thread == NULL) { + PPP_DEBUG_ERROR("Failed to create PPP lwIP receive thread"); + g_ppp_rx_thread_running = false; + return PPP_ERR_MEMORY; + } + + PPP_DEBUG_INFO("PPP lwIP receive thread created successfully (slipif-style)"); + return PPP_ERR_OK; +} + +/** + * @brief 停止PPP接收线程 + */ +ppp_error_t ppp_lwip_stop_receive_thread(void) +{ + if (g_ppp_rx_thread == NULL) { + return PPP_ERR_OK; + } + + PPP_DEBUG_INFO("Stopping PPP lwIP receive thread"); + + // 停止线程 + g_ppp_rx_thread_running = false; + + // 等待线程结束 + osal_msleep(100); + + // 销毁线程 + osal_kthread_destroy(g_ppp_rx_thread, 0); + g_ppp_rx_thread = NULL; + + PPP_DEBUG_INFO("PPP lwIP receive thread stopped"); + return PPP_ERR_OK; +} + +/** + * @brief 检查PPP接收线程是否运行 + */ +bool ppp_lwip_is_receive_thread_running(void) +{ + return g_ppp_rx_thread_running && (g_ppp_rx_thread != NULL); +} \ No newline at end of file diff --git a/code/sdk/zhihui/ppp/src/ppp_serial.c b/code/sdk/zhihui/ppp/src/ppp_serial.c index b871f2bb8..73b7d690f 100644 --- a/code/sdk/zhihui/ppp/src/ppp_serial.c +++ b/code/sdk/zhihui/ppp/src/ppp_serial.c @@ -10,12 +10,14 @@ #include "soc_osal.h" #include "securec.h" #include +#include "arch_port.h" /* 串口上下文结构 - 优化缓存机制 */ typedef struct { bool initialized; ppp_serial_mode_t current_mode; uint8_t uart_bus; + uint8_t irq_num; /* UART配置参数 */ uart_pin_config_t pin_config; @@ -69,6 +71,10 @@ 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); + +/* IRQ相关代码已移除 - 使用简化的直接UART读取方式 */ /** * @brief 初始化PPP串口 - 统一缓冲区管理 @@ -85,6 +91,7 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config) /* 打印配置参数 */ PPP_DEBUG_INFO("Configuration parameters:"); PPP_DEBUG_INFO(" - UART Bus: %u", config->uart_bus); + PPP_DEBUG_INFO(" - IRQ Num: %u", config->irq_num); PPP_DEBUG_INFO(" - Baudrate: %u", config->baudrate); PPP_DEBUG_INFO(" - TX Pin: %u", config->tx_pin); PPP_DEBUG_INFO(" - RX Pin: %u", config->rx_pin); @@ -94,6 +101,7 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config) /* 配置UART参数 */ g_serial_ctx.uart_bus = config->uart_bus; + g_serial_ctx.irq_num = config->irq_num; g_serial_ctx.pin_config.tx_pin = config->tx_pin; g_serial_ctx.pin_config.rx_pin = config->rx_pin; g_serial_ctx.uart_attr.baud_rate = config->baudrate; @@ -275,22 +283,9 @@ ppp_error_t ppp_serial_switch_to_ppp_mode(void) osal_mutex_unlock(&g_serial_ctx.tx_mutex); PPP_DEBUG_INFO("TX buffer cleared for mode switch"); - /* 注册UART接收回调,启用软件缓冲区管理 */ - PPP_DEBUG_INFO("Registering UART RX callback..."); - PPP_DEBUG_INFO(" - Bus: %u", g_serial_ctx.uart_bus); - PPP_DEBUG_INFO(" - Condition: UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE"); - PPP_DEBUG_INFO(" - Buffer size: %u", g_serial_ctx.rx_buffer_size); - PPP_DEBUG_INFO(" - Callback function: %p", ppp_serial_rx_callback); - - errcode_t ret = uapi_uart_register_rx_callback(g_serial_ctx.uart_bus, - UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE, - g_serial_ctx.rx_buffer_size, - ppp_serial_rx_callback); - if (ret != ERRCODE_SUCC) { - PPP_DEBUG_ERROR("Failed to register UART RX callback: error code = %d (0x%x)", ret, ret); - return PPP_ERR_UART; - } - PPP_DEBUG_INFO("UART RX callback registered successfully"); + /* PPP数据模式:使用优化的直接UART读取,增加超时时间获取完整数据 */ + PPP_DEBUG_INFO("PPP Data Mode: Using optimized direct UART read with longer timeout"); + PPP_DEBUG_INFO("This approach is more reliable than callback mechanism"); g_serial_ctx.current_mode = PPP_SERIAL_MODE_PPP_DATA; PPP_DEBUG_INFO("Mode switched to PPP_DATA (%d)", g_serial_ctx.current_mode); @@ -317,11 +312,6 @@ ppp_error_t ppp_serial_switch_to_at_mode(void) PPP_DEBUG_INFO("Current mode: %d (PPP_DATA) -> %d (AT)", g_serial_ctx.current_mode, PPP_SERIAL_MODE_AT); PPP_DEBUG_INFO("UART Bus: %u", g_serial_ctx.uart_bus); - /* 取消注册UART接收回调,回到直接UART读取模式 */ - PPP_DEBUG_INFO("Unregistering UART RX callback..."); - uapi_uart_unregister_rx_callback(g_serial_ctx.uart_bus); - PPP_DEBUG_INFO("UART RX callback unregistered"); - /* 清空接收缓冲区 */ PPP_DEBUG_INFO("Clearing RX buffer..."); osal_mutex_lock(&g_serial_ctx.rx_mutex); @@ -342,6 +332,12 @@ ppp_error_t ppp_serial_switch_to_at_mode(void) 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_INFO("Switching from PPP data mode to AT mode"); + PPP_DEBUG_INFO("No callback cleanup needed (using direct UART read)"); + } + g_serial_ctx.current_mode = PPP_SERIAL_MODE_AT; PPP_DEBUG_INFO("Mode switched to AT (%d)", g_serial_ctx.current_mode); PPP_DEBUG_INFO("=== AT Mode Switch Complete ==="); @@ -364,7 +360,7 @@ ppp_error_t ppp_serial_write(const uint8_t *data, uint32_t length) PPP_DEBUG_INFO("UART Bus: %u", g_serial_ctx.uart_bus); ppp_error_t result = PPP_ERR_OK; - + int32_t write_result = 0; switch (g_serial_ctx.current_mode) { case PPP_SERIAL_MODE_AT: /* AT命令模式:直接使用UART发送 */ @@ -374,7 +370,7 @@ ppp_error_t ppp_serial_write(const uint8_t *data, uint32_t length) PPP_DEBUG_INFO("Calling uapi_uart_write(bus=%u, data=%p, len=%u, timeout=1000)...", g_serial_ctx.uart_bus, data, length); - int32_t write_result = uapi_uart_write(g_serial_ctx.uart_bus, data, length, 1000); + write_result = uapi_uart_write(g_serial_ctx.uart_bus, data, length, 1000); PPP_DEBUG_INFO("uapi_uart_write returned: %d (expected: %u)", write_result, length); if (write_result != (int32_t)length) { @@ -390,60 +386,34 @@ ppp_error_t ppp_serial_write(const uint8_t *data, uint32_t length) break; case PPP_SERIAL_MODE_PPP_DATA: - /* PPP数据模式:使用缓冲发送 */ - PPP_DEBUG_INFO("Buffering %u bytes for PPP data mode", length); - // PPP_DEBUG_HEXDUMP(data, length); + /* PPP数据模式:直接使用UART发送(与AT模式一致) */ + PPP_DEBUG_INFO("Sending %u bytes via UART (PPP data mode)", length); - osal_mutex_lock(&g_serial_ctx.tx_mutex); - - /* 检查缓冲区空间 */ - uint32_t available_space = ppp_serial_tx_buffer_available_space(); - if (available_space < length) { - PPP_DEBUG_WARN("TX buffer insufficient space: need %u, available %u", length, available_space); - - /* 先尝试发送现有缓冲区数据 */ - osal_mutex_unlock(&g_serial_ctx.tx_mutex); - ppp_error_t flush_result = ppp_serial_flush_tx(); - if (flush_result != PPP_ERR_OK) { - PPP_DEBUG_ERROR("Failed to flush TX buffer before new write"); - result = flush_result; - break; - } - osal_mutex_lock(&g_serial_ctx.tx_mutex); - - /* 重新检查空间 */ - available_space = ppp_serial_tx_buffer_available_space(); - if (available_space < length) { - PPP_DEBUG_ERROR("TX buffer still insufficient after flush: need %u, available %u", - length, available_space); - osal_mutex_unlock(&g_serial_ctx.tx_mutex); - g_serial_ctx.tx_errors++; - result = PPP_ERR_UART; - break; - } + // 打印PPP数据包内容用于调试 + PPP_DEBUG_PRINT("PPP TX Data: "); + for (uint32_t i = 0; i < length && i < 16; i++) { + PPP_DEBUG_PRINT("%02X ", data[i]); } - - /* 将数据复制到发送缓冲区 */ - for (uint32_t i = 0; i < length; i++) { - g_serial_ctx.tx_buffer[g_serial_ctx.tx_head] = data[i]; - g_serial_ctx.tx_head = (g_serial_ctx.tx_head + 1) % g_serial_ctx.tx_buffer_size; - g_serial_ctx.tx_count++; + if (length > 16) { + PPP_DEBUG_PRINT("... (total %u bytes)", length); } + PPP_DEBUG_PRINT("\n"); - uint32_t buffered_count = 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, data, length); - PPP_DEBUG_INFO("Buffered %u bytes (total buffered: %u bytes)", length, buffered_count); + write_result = uapi_uart_write(g_serial_ctx.uart_bus, data, length, 1000); + PPP_DEBUG_INFO("uapi_uart_write returned: %d (expected: %u)", write_result, length); - /* 智能flush策略:根据PPP协议特性决定是否立即发送 */ - if (ppp_serial_should_immediate_flush(data, length, buffered_count)) { - PPP_DEBUG_INFO("Smart flush triggered (buffered: %u, packet: %u bytes)", - buffered_count, length); - result = ppp_serial_flush_tx(); - g_serial_ctx.last_tx_time = ppp_serial_get_current_time_ms(); + if (write_result != (int32_t)length) { + PPP_DEBUG_ERROR("UART write failed in PPP data mode: returned %d, expected %u", write_result, length); + 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 += length; - PPP_DEBUG_INFO("Data buffered smartly (total: %u bytes, will flush when appropriate)", buffered_count); + PPP_DEBUG_INFO("Sent %u bytes successfully via UART (PPP mode, total tx: %u bytes)", + length, g_serial_ctx.tx_bytes); } break; @@ -475,22 +445,51 @@ ppp_error_t ppp_serial_read(uint8_t *buffer, uint32_t buffer_size, uint32_t *byt switch (g_serial_ctx.current_mode) { case PPP_SERIAL_MODE_AT: - /* AT命令模式:直接从UART读取 */ + /* AT命令模式:直接从UART读取 */ { int32_t read_result = uapi_uart_read(g_serial_ctx.uart_bus, buffer, buffer_size, 100); if (read_result > 0) { *bytes_read = (uint32_t)read_result; g_serial_ctx.rx_bytes += *bytes_read; PPP_DEBUG_DEBUG("Read %u bytes via UART (AT mode)", *bytes_read); - // PPP_DEBUG_HEXDUMP(buffer, *bytes_read); } else if (read_result < 0) { - PPP_DEBUG_ERROR("UART read error in AT mode: %d", read_result); + PPP_DEBUG_ERROR("UART read error: %d", read_result); g_serial_ctx.rx_errors++; result = PPP_ERR_UART; } } break; + case PPP_SERIAL_MODE_PPP_DATA: + /* PPP数据模式:使用优化的直接UART读取,增加超时时间 */ + { + /* 使用更长的超时时间来获取更完整的数据包 */ + int32_t read_result = uapi_uart_read(g_serial_ctx.uart_bus, buffer, buffer_size, 500); + if (read_result > 0) { + *bytes_read = (uint32_t)read_result; + g_serial_ctx.rx_bytes += *bytes_read; + + PPP_DEBUG_INFO("PPP UART Read: Received %u bytes (optimized mode)", *bytes_read); + PPP_DEBUG_PRINT("PPP RX Data: "); + for (uint32_t i = 0; i < *bytes_read && i < 16; i++) { + PPP_DEBUG_PRINT("%02X ", buffer[i]); + } + if (*bytes_read > 16) { + PPP_DEBUG_PRINT("... (total %u bytes)", *bytes_read); + } + PPP_DEBUG_PRINT("\n"); + } else if (read_result < 0) { + PPP_DEBUG_ERROR("UART read error in PPP mode: %d", read_result); + g_serial_ctx.rx_errors++; + result = PPP_ERR_UART; + } else { + /* read_result == 0, 超时但无错误 */ + *bytes_read = 0; + result = PPP_ERR_OK; + } + } + break; +#if 0 case PPP_SERIAL_MODE_PPP_DATA: /* PPP数据模式:从软件环形缓冲区读取 */ osal_mutex_lock(&g_serial_ctx.rx_mutex); @@ -515,7 +514,7 @@ ppp_error_t ppp_serial_read(uint8_t *buffer, uint32_t buffer_size, uint32_t *byt PPP_DEBUG_DEBUG("Read %u bytes from software buffer (PPP data mode)", to_read); // PPP_DEBUG_HEXDUMP(buffer, to_read); break; - +#endif default: PPP_DEBUG_ERROR("Invalid serial mode: %d", g_serial_ctx.current_mode); result = PPP_ERR_INVALID_PARAM; @@ -793,6 +792,9 @@ static void ppp_serial_rx_callback(const void *buffer, uint16_t length, bool rem { (void)remaining; + /* UART接收回调函数:将数据存储到环形缓冲区 */ + PPP_DEBUG_INFO("UART Callback: Received %u bytes", length); + if (!buffer || length == 0) { return; } @@ -828,7 +830,17 @@ static void ppp_serial_rx_callback(const void *buffer, uint16_t length, bool rem g_serial_ctx.rx_callback(data, length, g_serial_ctx.rx_callback_arg); } - PPP_DEBUG_DEBUG("Received %u bytes", length); + PPP_DEBUG_INFO("UART Callback: Received %u bytes", length); + + // 打印前8字节用于调试 + PPP_DEBUG_PRINT("UART RX Data: "); + for (uint16_t i = 0; i < length && i < 8; i++) { + PPP_DEBUG_PRINT("%02X ", data[i]); + } + if (length > 8) { + PPP_DEBUG_PRINT("... (total %u bytes)", length); + } + PPP_DEBUG_PRINT("\n"); } /** @@ -1021,4 +1033,55 @@ uint32_t ppp_serial_tx_available(void) osal_mutex_unlock(&g_serial_ctx.tx_mutex); return count; -} \ No newline at end of file +} + +/* + * 注意:以下IRQ处理函数暂时不使用,因为UART回调机制已经包含了中断处理 + * 如果需要更底层的中断控制,可以取消注释并调试IRQ冲突问题 + */ + +#if 0 +/** + * @brief UART中断处理函数 + */ +static void _ppp_serial_irq_handler(uint32_t irq_num, void *arg) +{ + (void)irq_num; + (void)arg; + + /* 调用HAL层的UART中断处理函数 */ + hal_uart_irq_handler(g_serial_ctx.uart_bus); +} + +/** + * @brief 注册UART中断 + */ +static ppp_error_t ppp_serial_register_irq(void) +{ + PPP_DEBUG_INFO("Registering UART IRQ %d for bus %u", SIO_UART_IRQ_NUM, g_serial_ctx.uart_bus); + + int32_t ret = osal_irq_request(SIO_UART_IRQ_NUM, _ppp_serial_irq_handler, NULL, "ppp_uart", 0); + if (ret != 0) { + PPP_DEBUG_ERROR("Failed to register UART IRQ %d: %d", SIO_UART_IRQ_NUM, ret); + return PPP_ERR_UART; + } + + PPP_DEBUG_INFO("UART IRQ %d registered successfully", SIO_UART_IRQ_NUM); + + osal_irq_set_priority(SIO_UART_IRQ_NUM, irq_prio(SIO_UART_IRQ_NUM)); + osal_irq_enable(SIO_UART_IRQ_NUM); + + return PPP_ERR_OK; +} + +/** + * @brief 注销UART中断 + */ +static ppp_error_t ppp_serial_unregister_irq(void) +{ + osal_irq_free(SIO_UART_IRQ_NUM, NULL); + osal_irq_disable(SIO_UART_IRQ_NUM); + PPP_DEBUG_INFO("UART IRQ %d unregistered successfully", SIO_UART_IRQ_NUM); + return PPP_ERR_OK; +} +#endif \ No newline at end of file