#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
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;
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
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
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=<interface_name>\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" },
{ (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 *)" " },
*/
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连接状态
*/
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
#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 }
#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大小
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 // 错误状态
*/
typedef struct {
uint8_t uart_bus; // UART总线号
+ uint8_t irq_num; // UART IRQ引脚
uint32_t baudrate; // 波特率
uint8_t tx_pin; // 发送引脚
uint8_t rx_pin; // 接收引脚
#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;
// 外部声明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模块
*/
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,
.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);
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;
+ }
}
/**
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;
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;
}
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;
}
// 1. 停止PPP数据接收线程
- ppp_stop_data_receive_thread();
+ ppp_lwip_stop_receive_thread();
// 2. 断开lwIP PPP连接
ppp_lwip_disconnect();
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;
}
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模式
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测试接口实现 ========== */
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
}
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"')
}
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;
}
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;
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) {
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;
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
}
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数据
*/
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
}
(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));
/* 获取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);
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",
(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;
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;
}
}
+/* 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
*/
(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
--- /dev/null
+/**
+ * @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 <stdlib.h>
+#include <string.h>
+
+/* 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
#include "soc_osal.h"
#include "securec.h"
#include <string.h>
+#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;
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串口 - 统一缓冲区管理
/* 打印配置参数 */
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);
/* 配置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;
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);
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);
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 ===");
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发送 */
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) {
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;
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);
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;
{
(void)remaining;
+ /* UART接收回调函数:将数据存储到环形缓冲区 */
+ PPP_DEBUG_INFO("UART Callback: Received %u bytes", length);
+
if (!buffer || length == 0) {
return;
}
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");
}
/**
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