custom_check_factory_test_flag();\r
startup_post_init();\r
#endif\r
+\r
set_startup_finish_flag();\r
-#ifdef SUPPORT_LEINIAO\r
-#ifdef CUSTOM_UTILS\r
- if(!custom_get_factory_test_flag())\r
-#endif\r
- uapi_ln_http_server_init();\r
-#endif\r
+\r
}\r
\r
void thread_pri_init(void)\r
'AUDIO_SMARTPA_AW88082',
'LCD_JD9885',
'SUPPORT_LEINIAO',
+ # 'SKIP_LN_PROTOCOL_TEST',
],
#添加自定义应用
'ram_component': [
/** UART_BUS_0, which is used to at cmd and debug print in wstp version,
* and which is used to testustie and debug print in testsuite version
*/
- #if defined(SUPPORT_CAT1_SERVICE) || defined(SUPPORT_PPP_SERVICE)
+ #if defined(SUPPORT_CAT1_SERVICE)
{
{
.tx_pin = PIN_NONE,
true,
#endif
},
-
+ #elif defined(SUPPORT_PPP_SERVICE)
+ {
+ {
+ .tx_pin = S_MGPIO19,
+ .rx_pin = S_MGPIO20,
+ .cts_pin = PIN_NONE,
+ .rts_pin = PIN_NONE
+ },
+ {
+ .tx_pin_mode = (pin_mode_t)HAL_PIO_FUNC_UART1,
+ .rx_pin_mode = (pin_mode_t)HAL_PIO_FUNC_UART1,
+ .cts_pin_mode = (pin_mode_t)HAL_PIO_FUNC_MAX,
+ .rts_pin_mode = (pin_mode_t)HAL_PIO_FUNC_MAX
+ },
+ UART_0_IRQN,
+ (osal_irq_handler)irq_uart0_handler,
+ NULL,
+ {
+ .baud_rate = CUSTOM_UART_RATE,
+ .data_bits = UART_DATA_BIT_8,
+ .parity = UART_PARITY_NONE,
+ .stop_bits = UART_STOP_BIT_1,
+ },
+ {
+ .rx_buffer_size = UART_RX_BUFFER_SIZE,
+ .rx_buffer = g_uart0_rx_buffer,
+ },
+ NULL,
+ false,
+ },
#else // SUPPORT_CAT1_SERVICE
{
{
}
if (mail.cmd == LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN)
{
+
+ #ifdef SKIP_LN_PROTOCOL_TEST
+ continue;
+ #endif
if(get_is_ln_get_device_token_success() == 1)
{
printf("设备Token已经获取\n");
+++ /dev/null
-
\ No newline at end of file
+++ /dev/null
-
\ No newline at end of file
+++ /dev/null
-
\ No newline at end of file
+++ /dev/null
-#!/bin/bash
-
-# PPP模块编译测试脚本
-# 用于验证PPP模块的编译完整性
-
-echo "=========================================="
-echo "PPP Module Build Test"
-echo "=========================================="
-
-# 设置项目根目录
-PROJECT_ROOT=$(cd "$(dirname "$0")/../../.." && pwd)
-PPP_DIR="$PROJECT_ROOT/zhihui/ppp"
-
-echo "Project Root: $PROJECT_ROOT"
-echo "PPP Directory: $PPP_DIR"
-
-# 检查必要文件是否存在
-echo ""
-echo "Checking required files..."
-
-required_files=(
- "include/ppp_api.h"
- "include/ppp_config.h"
- "include/ppp_types.h"
- "include/ppp_at_handler.h"
- "include/ppp_serial.h"
- "include/ppp_lwip.h"
- "include/ppp_debug.h"
- "src/ppp_api.c"
- "src/ppp_at_handler.c"
- "src/ppp_serial.c"
- "src/ppp_lwip.c"
- "src/ppp_debug.c"
- "CMakeLists.txt"
- "README.md"
-)
-
-missing_files=0
-for file in "${required_files[@]}"; do
- if [ -f "$PPP_DIR/$file" ]; then
- echo "✓ $file"
- else
- echo "✗ $file (MISSING)"
- missing_files=$((missing_files + 1))
- fi
-done
-
-if [ $missing_files -gt 0 ]; then
- echo ""
- echo "ERROR: $missing_files required files are missing!"
- exit 1
-fi
-
-echo ""
-echo "All required files found!"
-
-# 检查头文件包含关系
-echo ""
-echo "Checking header dependencies..."
-
-# 简单的语法检查(如果有gcc可用)
-if command -v gcc >/dev/null 2>&1; then
- echo "Running syntax check with GCC..."
-
- # 创建临时测试文件
- test_file="/tmp/ppp_test.c"
- cat > "$test_file" << 'EOF'
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-
-// 模拟系统头文件
-#define ERRCODE_SUCC 0
-#define OSAL_SUCCESS 0
-#define OSAL_WAIT_FOREVER -1
-#define UART_BUS_1 1
-#define S_MGPIO33 33
-#define S_MGPIO34 34
-#define PIN_NONE 0xFF
-#define UART_DATA_BIT_8 8
-#define UART_PARITY_NONE 0
-#define UART_STOP_BIT_1 1
-#define UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE 1
-
-typedef int errcode_t;
-typedef void* osal_mutex;
-typedef void* osal_semaphore;
-typedef void* osal_timer;
-typedef void* osal_task;
-
-typedef struct {
- uint8_t tx_pin;
- uint8_t rx_pin;
- uint8_t cts_pin;
- uint8_t rts_pin;
-} uart_pin_config_t;
-
-typedef struct {
- uint32_t baud_rate;
- uint8_t data_bits;
- uint8_t parity;
- uint8_t stop_bits;
-} uart_attr_t;
-
-typedef struct {
- uint32_t rx_buffer_size;
- uint8_t *rx_buffer;
-} uart_buffer_config_t;
-
-// 模拟函数声明
-#define PRINT printf
-#define osal_kmalloc malloc
-#define osal_kfree free
-#define osal_get_tick() 0
-#define osal_msleep(x)
-int osal_mutex_init(osal_mutex *mutex) { return 0; }
-int osal_mutex_destroy(osal_mutex mutex) { return 0; }
-int osal_mutex_lock(osal_mutex mutex) { return 0; }
-int osal_mutex_unlock(osal_mutex mutex) { return 0; }
-int osal_sem_init(osal_semaphore *sem, int value) { return 0; }
-int osal_sem_destroy(osal_semaphore sem) { return 0; }
-int osal_sem_wait(osal_semaphore sem, int timeout) { return 0; }
-int osal_sem_signal(osal_semaphore sem) { return 0; }
-int memset_s(void *dest, size_t destMax, int c, size_t count) { return 0; }
-int memcpy_s(void *dest, size_t destMax, const void *src, size_t count) { return 0; }
-int snprintf_s(char *strDest, size_t destMax, size_t count, const char *format, ...) { return 0; }
-
-EOF
-
- # 添加PPP头文件内容进行语法检查
- echo '#include "'$PPP_DIR'/include/ppp_config.h"' >> "$test_file"
- echo '#include "'$PPP_DIR'/include/ppp_types.h"' >> "$test_file"
- echo '#include "'$PPP_DIR'/include/ppp_debug.h"' >> "$test_file"
- echo '#include "'$PPP_DIR'/include/ppp_api.h"' >> "$test_file"
-
- echo "int main() { return 0; }" >> "$test_file"
-
- if gcc -fsyntax-only -I"$PPP_DIR/include" "$test_file" 2>/dev/null; then
- echo "✓ Header syntax check passed"
- else
- echo "✗ Header syntax check failed"
- echo "Running detailed check..."
- gcc -fsyntax-only -I"$PPP_DIR/include" "$test_file"
- fi
-
- rm -f "$test_file"
-else
- echo "GCC not available, skipping syntax check"
-fi
-
-# 统计代码行数
-echo ""
-echo "Code statistics:"
-total_lines=0
-for file in src/*.c include/*.h; do
- if [ -f "$PPP_DIR/$file" ]; then
- lines=$(wc -l < "$PPP_DIR/$file")
- echo " $file: $lines lines"
- total_lines=$((total_lines + lines))
- fi
-done
-echo " Total: $total_lines lines"
-
-# 检查文档
-echo ""
-echo "Documentation:"
-if [ -f "$PPP_DIR/README.md" ]; then
- readme_lines=$(wc -l < "$PPP_DIR/README.md")
- echo " README.md: $readme_lines lines"
-fi
-
-if [ -f "$PPP_DIR/example/ppp_example.c" ]; then
- example_lines=$(wc -l < "$PPP_DIR/example/ppp_example.c")
- echo " Example code: $example_lines lines"
-fi
-
-echo ""
-echo "=========================================="
-echo "PPP Module Build Test Completed"
-echo "=========================================="
-echo ""
-echo "Summary:"
-echo " ✓ All required files present"
-echo " ✓ Header dependencies OK"
-echo " ✓ Code statistics generated"
-echo " ✓ Documentation available"
-echo ""
-echo "The PPP module is ready for integration!"
-echo ""
-echo "Next steps:"
-echo "1. Add PPP module to main CMakeLists.txt"
-echo "2. Configure lwIP with PPP support"
-echo "3. Test with actual hardware"
-echo ""
\ No newline at end of file
--- /dev/null
+# /etc/ppp/peers/Neoway-pppdial
+# Usage:root@neoway:~# pppd call Neoway-pppdial
+
+crtscts
+modem
+
+# Hide password in debug messages
+#hide-password
+
+# The phone is not required to authenticate
+noauth
+
+# The chat script (be sure to edit that file,too!)
+connect '/usr/sbin/chat -s -v -f /etc/ppp/peers/chat'
+
+# The close script(be sure to edit that file,too!)
+#disconnect '/usr/sbin/chat -s -v -f /etc/ppp/peers/Neoway-chat-disconnect'
+
+# Debug info from pppd
+debug
+
+# Serial Device to whih phone is connect
+#/dev/ttyACM7
+/dev/ttyUSB0
+#/dev/ttyUSB4
+#/dev/mux0
+
+# Serial port line speed
+115200
+
+
+# If you want to use the link as your gateway
+defaultroute
+
+# pppd must not propose any IP address to the peer
+noipdefault
+
+# No ppp compression
+novj
+novjccomp
+noccp
+ipcp-accept-local
+ipcp-accept-remote
+local
+
+# For sanity, keep a lock on the serial line
+lock
+dump
+
+# Keep pppd attached to the terminal
+# Comment this to get daemon mode pppd
+nodetach
+#user "card@cc.sg.jl"
+#0.0.0.0:0.0.0.0
+#password "card@123"
+# Hardware flow control
+#crtscts
+#remotename 3gppp
+#ipparam 3gppp
+
+# Ask the peer for up to 2 DNS server addresses
+usepeerdns
+
++ipv6
#include "ppp_serial.h"
#include "ppp_types.h"
#include "ppp_api.h"
+#include "ppp_lwip.h"
#include "ppp_at_handler.h"
#include "ppp_debug_manager.h"
#include "zhihui_tcp_test.h"
#include "ppp_example.h"
+#include "uart.h"
}
#endif
-/* PPP串口模式切换测试指令 */
-static errcode_t at_ppp_mode_switch(uint8_t *para, uint32_t paraLen)
-{
- uint8_t argv[CUSTOM_UTILS_MAX_ARGC][CUSTOM_UTILS_MAX_ARGV_LEN];
- uint32_t argc;
-
- if (ConvertCmdToParam(para, paraLen, argv, &argc) != CUSTOM_UTILS_SUCCESS) {
- ppp_print_err("PPP MODE SWITCH Convert Command Failed\n");
- return ERRCODE_FAIL;
- }
-
- if (argc != 1) {
- ppp_print_err("PPP MODE SWITCH Set Parameter Failed argc %d\nUsage: AT^PPPMODE=AT|PPP\n", argc);
- return ERRCODE_FAIL;
- }
-
- errcode_t ret = ppp_test_switch_mode((char*)argv[0]);
- if (ret == ERRCODE_SUCC) {
- ppp_print_info("PPP MODE SWITCH: Successfully switched to %s mode\n", argv[0]);
- } else {
- ppp_print_err("PPP MODE SWITCH: Failed to switch to %s mode, error: %d\n", argv[0], ret);
- }
-
- return ret;
-}
-
/* PPP串口状态查询指令 */
static errcode_t at_ppp_status(uint8_t *para, uint32_t paraLen)
{
}
}
-/* PPP串口测试指令 */
-static errcode_t at_ppp_test(uint8_t *para, uint32_t paraLen)
-{
- (void)para;
- (void)paraLen;
-
- ppp_print_info("PPP TEST: Starting PPP serial test...\n");
-
- errcode_t ret = ppp_test_uart_function();
- if (ret == ERRCODE_SUCC) {
- ppp_print_info("PPP TEST: UART test completed successfully\n");
- } else {
- ppp_print_err("PPP TEST: UART test failed, error: %d\n", ret);
- }
-
- return ret;
-}
-
/* PPP智能flush测试指令 */
static errcode_t at_ppp_flush(uint8_t *para, uint32_t paraLen)
{
ppp_print_info("PPP RUNTIME SHOW: Current runtime status:\n");
// 显示当前runtime状态
- ppp_print_info("\n=== Current Runtime Status ===\n");
- ppp_print_info("Power Status: %s\n", cat1_api_runtime_get_cat1_powerstat() ? "ON" : "OFF");
- ppp_print_info("Network Status: %s\n", cat1_api_runtime_get_cat1_networkstat() ? "CONNECTED" : "DISCONNECTED");
+ ppp_print_info("\n=== Current Runtime Status ===");
+ ppp_print_info("Power Status: %s", cat1_api_runtime_get_cat1_powerstat() ? "ON" : "OFF");
+ ppp_print_info("Network Status: %s", cat1_api_runtime_get_cat1_networkstat() ? "CONNECTED" : "DISCONNECTED");
int signal = cat1_api_runtime_get_cat1_signal();
if (signal == 99) {
- ppp_print_info("Signal Strength: No Signal (99)\n");
+ ppp_print_info("Signal Strength: No Signal (99)");
} else {
- ppp_print_info("Signal Strength: %d/31 (%s)\n", signal,
+ ppp_print_info("Signal Strength: %d/31 (%s)", signal,
signal >= 20 ? "Excellent" :
signal >= 15 ? "Good" :
signal >= 10 ? "Fair" :
signal >= 5 ? "Poor" : "Very Poor");
}
- ppp_print_info("SIM Status: %s\n", cat1_api_runtime_get_cat1_simstat() ? "NORMAL" : "ERROR");
+ ppp_print_info("SIM Status: %s", cat1_api_runtime_get_cat1_simstat() ? "NORMAL" : "ERROR");
uint8_t net_type = cat1_api_runtime_get_cat1_networktype();
const char* net_type_str = "Unknown";
case 5: net_type_str = "Registered (Roaming)"; break;
default: net_type_str = "Invalid"; break;
}
- ppp_print_info("Network Type: %d (%s)\n", net_type, net_type_str);
+ ppp_print_info("Network Type: %d (%s)", net_type, net_type_str);
char* operator = cat1_api_runtime_get_cat1_operator();
- ppp_print_info("Operator: %s\n", (operator && strlen(operator) > 0) ? operator : "Unknown");
+ ppp_print_info("Operator: %s", (operator && strlen(operator) > 0) ? operator : "Unknown");
char* imei = cat1_api_runtime_get_cat1_imei();
- ppp_print_info("IMEI: %s\n", (imei && strlen(imei) > 0) ? imei : "Unknown");
+ ppp_print_info("IMEI: %s", (imei && strlen(imei) > 0) ? imei : "Unknown");
char* iccid = cat1_api_runtime_get_cat1_iccid();
- ppp_print_info("ICCID: %s\n", (iccid && strlen(iccid) > 0) ? iccid : "Unknown");
+ ppp_print_info("ICCID: %s", (iccid && strlen(iccid) > 0) ? iccid : "Unknown");
char* version = cat1_api_runtime_get_cat1_modemver();
- ppp_print_info("Modem Version: %s\n", (version && strlen(version) > 0) ? version : "Unknown");
-
- ppp_print_info("===============================\n");
+ ppp_print_info("Modem Version: %s", (version && strlen(version) > 0) ? version : "Unknown");
+
+ ppp_print_info("===============================");
+
+ // 显示PPP输出统计信息
+ ppp_lwip_output_stats_t ppp_stats;
+ if (ppp_lwip_get_output_stats(&ppp_stats) == PPP_ERR_OK) {
+ ppp_print_info("\n=== PPP Output Statistics ===");
+ ppp_print_info("Total Output Packets: %llu", ppp_stats.total_packets);
+ ppp_print_info("Total Output Bytes: %llu", ppp_stats.total_bytes);
+ ppp_print_info("LCP Packets: %u", ppp_stats.lcp_packets);
+ ppp_print_info("IPCP Packets: %u", ppp_stats.ipcp_packets);
+ ppp_print_info("IP Packets: %u", ppp_stats.ip_packets);
+ ppp_print_info("Other Protocol Packets: %u", ppp_stats.other_packets);
+ ppp_print_info("Failed Sends: %u", ppp_stats.failed_sends);
+
+ // 计算PPP输出统计的运行时间和速率
+ uint32_t current_time = ppp_stats.last_packet_time;
+ if (current_time == 0) {
+ // 如果没有最后包时间,使用当前时间的简单估算
+ current_time = ppp_stats.start_time + 10000; // 假设运行了10秒
+ }
+ uint32_t ppp_elapsed_ms = current_time - ppp_stats.start_time;
+ uint32_t ppp_elapsed_sec = ppp_elapsed_ms / 1000;
+
+ if (ppp_elapsed_sec > 0) {
+ ppp_print_info("PPP Stats Duration: %u seconds", ppp_elapsed_sec);
+ }
+
+ if (ppp_elapsed_ms > 0 && ppp_stats.total_bytes > 0) {
+ uint64_t ppp_throughput_bps = (ppp_stats.total_bytes * 1000) / ppp_elapsed_ms;
+ ppp_print_info("PPP Output Throughput: %llu bytes/s", ppp_throughput_bps);
+
+ float ppp_packet_rate = (float)ppp_stats.total_packets * 1000 / ppp_elapsed_ms;
+ ppp_print_info("PPP Output Packet Rate: %.1f packets/s", ppp_packet_rate);
+ }
+
+ // 计算成功率
+ uint64_t total_attempts = ppp_stats.total_packets + ppp_stats.failed_sends;
+ if (total_attempts > 0) {
+ float success_rate = (float)ppp_stats.total_packets / total_attempts * 100;
+ ppp_print_info("PPP Output Success Rate: %.1f%%", success_rate);
+ }
+
+ ppp_print_info("=============================");
+ } else {
+ ppp_print_info("\n=== PPP Output Statistics ===");
+ ppp_print_info("Failed to get PPP output statistics");
+ ppp_print_info("=============================");
+ }
ppp_lwip_print_discard_stats();
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);
+ errcode_t ret = ppp_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);
/**
* @brief AT^PPPTCPPERF - PPP TCP性能测试
- * @param para 参数: 服务器地址,端口,连接数,测试时间
+ * @param para 参数: 服务器地址,端口,连接数,测试时间[,接收超时(ms)]
* @param paraLen 参数长度
*/
static errcode_t at_ppp_tcp_performance_test(uint8_t *para, uint32_t paraLen)
{
if (!para || paraLen == 0) {
PRINT("[PPP_ERR]PPP TCP PERF: Missing parameters\r\n");
- PRINT("[PPP_INFO]Usage: AT^PPPTCPPERF=<host>,<port>,<connections>,<time>\r\n");
+ PRINT("[PPP_INFO]Usage: AT^PPPTCPPERF=<host>,<port>,<connections>,<time>[,<recv_timeout_ms>]\r\n");
PRINT("[PPP_INFO]Example: AT^PPPTCPPERF=110.42.224.129,8910,5,30\r\n");
+ PRINT("[PPP_INFO]Example: AT^PPPTCPPERF=110.42.224.129,8910,5,30,2000\r\n");
return ERRCODE_FAIL;
}
uint8_t argv[CUSTOM_UTILS_MAX_ARGC][CUSTOM_UTILS_MAX_ARGV_LEN];
uint32_t argc;
- if (ConvertCmdToParam(para, paraLen, argv, &argc) != CUSTOM_UTILS_SUCCESS || argc != 4) {
- PRINT("[PPP_ERR]PPP TCP PERF: Invalid parameters, need 4 parameters, got %d\r\n", argc);
- PRINT("[PPP_INFO]Usage: AT^PPPTCPPERF=<host>,<port>,<connections>,<time>\r\n");
+ if (ConvertCmdToParam(para, paraLen, argv, &argc) != CUSTOM_UTILS_SUCCESS || (argc != 4 && argc != 5)) {
+ PRINT("[PPP_ERR]PPP TCP PERF: Invalid parameters, need 4 or 5 parameters, got %d\r\n", argc);
+ PRINT("[PPP_INFO]Usage: AT^PPPTCPPERF=<host>,<port>,<connections>,<time>[,<recv_timeout_ms>]\r\n");
return ERRCODE_FAIL;
}
int port = atoi((char*)argv[1]);
int connections = atoi((char*)argv[2]);
int test_time = atoi((char*)argv[3]);
+ int recv_timeout_ms = TCP_TEST_DEFAULT_RECV_TIMEOUT_MS; // 默认值
+
+ // 解析可选的接收超时参数
+ if (argc == 5) {
+ recv_timeout_ms = atoi((char*)argv[4]);
+ if (recv_timeout_ms < 100 || recv_timeout_ms > 30000) {
+ PRINT("[PPP_ERR]PPP TCP PERF: Invalid recv timeout %d (must be 100-30000 ms)\r\n", recv_timeout_ms);
+ return ERRCODE_FAIL;
+ }
+ }
// 参数验证
if (port < 1 || port > 65535) {
PRINT("[PPP_INFO]Target: %s:%d\r\n", server_host, port);
PRINT("[PPP_INFO]Connections: %d\r\n", connections);
PRINT("[PPP_INFO]Duration: %d seconds\r\n", test_time);
+ PRINT("[PPP_INFO]Receive Timeout: %d ms\r\n", recv_timeout_ms);
#ifdef SUPPORT_TCP_TEST
// 初始化TCP测试配置
config.server_port = (uint16_t)port;
config.test_duration = (uint32_t)test_time;
config.connection_count = (uint16_t)connections;
- config.verbose = false; // AT命令模式不使用详细输出
- config.send_interval_ms = 10; // 10ms间隔,适合AT命令模式
- config.data_min_size = 64; // 较小的数据包
- config.data_max_size = 1024; // 适中的最大包
+ config.verbose = true; // AT命令模式不使用详细输出
+ config.send_interval_ms = 100; // 100ms间隔,适合AT命令模式
+ config.data_min_size = 1024; // 较小的数据包
+ config.data_max_size = 4096; // 适中的最大包
+ config.recv_timeout_ms = (uint32_t)recv_timeout_ms; // 可配置的接收超时
// 初始化TCP测试
errcode_t ret = tcp_test_init();
PRINT("[PPP_INFO]Packets Received: %llu\r\n", stats.total_packets_received);
PRINT("[PPP_INFO]Bytes Sent: %llu\r\n", stats.total_bytes_sent);
PRINT("[PPP_INFO]Bytes Received: %llu\r\n", stats.total_bytes_received);
+ PRINT("[PPP_INFO]Total Send Errors: %u\r\n", stats.total_send_errors);
+ PRINT("[PPP_INFO]Total Receive Errors: %u\r\n", stats.total_recv_errors);
+ PRINT("[PPP_INFO]Total Incomplete Packets: %u\r\n", stats.total_incomplete_packets);
+ PRINT("[PPP_INFO]Total Incomplete Bytes: %u\r\n", stats.total_incomplete_bytes);
+ PRINT("[PPP_INFO]Total Pattern Errors: %u\r\n", stats.total_pattern_errors);
+ PRINT("[PPP_INFO]Max Send Throughput: %llu bytes/s\r\n", stats.max_send_throughput_bps);
+ PRINT("[PPP_INFO]Avg Send Throughput: %llu bytes/s\r\n", stats.avg_send_throughput_bps);
+ PRINT("[PPP_INFO]Max Receive Throughput: %llu bytes/s\r\n", stats.max_recv_throughput_bps);
+ PRINT("[PPP_INFO]Avg Receive Throughput: %llu bytes/s\r\n", stats.avg_recv_throughput_bps);
PRINT("[PPP_INFO]Total Errors: %d\r\n", stats.total_errors);
- PRINT("[PPP_INFO]Data Verification Errors: %d\r\n", stats.data_verification_errors);
// 计算传输速率
if (elapsed_ms > 0) {
PRINT("[PPP_INFO]========================================\r\n");
- return ERRCODE_SUCC;
+#endif /* SUPPORT_TCP_TEST */
+
+ // 获取并显示PPP输出统计(无论是否支持TCP测试都显示)
+ ppp_lwip_output_stats_t ppp_stats;
+ if (ppp_lwip_get_output_stats(&ppp_stats) == PPP_ERR_OK) {
+ PRINT("[PPP_INFO]=== PPP Output Statistics ===\r\n");
+ PRINT("[PPP_INFO]Total Output Packets: %llu\r\n", ppp_stats.total_packets);
+ PRINT("[PPP_INFO]Total Output Bytes: %llu\r\n", ppp_stats.total_bytes);
+ PRINT("[PPP_INFO]LCP Packets: %u\r\n", ppp_stats.lcp_packets);
+ PRINT("[PPP_INFO]IPCP Packets: %u\r\n", ppp_stats.ipcp_packets);
+ PRINT("[PPP_INFO]IP Packets: %u\r\n", ppp_stats.ip_packets);
+ PRINT("[PPP_INFO]Other Protocol Packets: %u\r\n", ppp_stats.other_packets);
+ PRINT("[PPP_INFO]Failed Sends: %u\r\n", ppp_stats.failed_sends);
+
+ // 计算PPP输出统计的运行时间和速率
+ uint32_t current_time = 0;
+#ifdef SUPPORT_TCP_TEST
+ current_time = tcp_test_get_time_ms();
+#else
+ // 使用简单的时间计算,如果没有TCP测试支持
+ current_time = ppp_stats.last_packet_time;
+#endif
+ uint32_t ppp_elapsed_ms = current_time - ppp_stats.start_time;
+ uint32_t ppp_elapsed_sec = ppp_elapsed_ms / 1000;
+ PRINT("[PPP_INFO]PPP Stats Duration: %u seconds\r\n", ppp_elapsed_sec);
+
+ if (ppp_elapsed_ms > 0 && ppp_stats.total_bytes > 0) {
+ uint64_t ppp_throughput_bps = (ppp_stats.total_bytes * 1000) / ppp_elapsed_ms;
+ PRINT("[PPP_INFO]PPP Output Throughput: %llu bytes/s\r\n", ppp_throughput_bps);
+
+ float ppp_packet_rate = (float)ppp_stats.total_packets * 1000 / ppp_elapsed_ms;
+ PRINT("[PPP_INFO]PPP Output Packet Rate: %.1f packets/s\r\n", ppp_packet_rate);
+ }
+
+ // 计算成功率
+ uint64_t total_attempts = ppp_stats.total_packets + ppp_stats.failed_sends;
+ if (total_attempts > 0) {
+ float success_rate = (float)ppp_stats.total_packets / total_attempts * 100;
+ PRINT("[PPP_INFO]PPP Output Success Rate: %.1f%%\r\n", success_rate);
+ }
+
+ PRINT("[PPP_INFO]========================================\r\n");
+ } else {
+ PRINT("[PPP_WARN]Failed to get PPP output statistics\r\n");
+ }
+ return ERRCODE_SUCC;
+
+#ifdef SUPPORT_TCP_TEST
#else
PRINT("[PPP_ERR]PPP TCP STATS: TCP test not supported in this build\r\n");
return ERRCODE_FAIL;
{ (char *)"AT^HTTPDOWNLOAD", custom_start_ota_download, (char *)" " },
{ (char *)"AT^CAT1LOGLEVEL", custom_enable_cat1_debug_log, (char *)" " },
/* PPP串口测试指令 */
- { (char *)"AT^PPPMODE", at_ppp_mode_switch, (char *)"AT|PPP" },
{ (char *)"AT^PPPSTATUS", at_ppp_status, (char *)" " },
{ (char *)"AT^PPPTRANS", at_ppp_transparent, (char *)"AT_COMMAND" },
- { (char *)"AT^PPPTEST", at_ppp_test, (char *)" " },
{ (char *)"AT^PPPFLUSH", at_ppp_flush, (char *)" " },
/* PPP模块化函数测试指令 */
{ (char *)"AT^PPPENVINIT", at_ppp_env_init, (char *)" " },
return -1;
}
- /* 3. 注册事件回调函数 */
- PRINT("Registering PPP event callback...\r\n");
- ret = ppp_register_event_callback(ppp_event_callback);
- if (ret != ERRCODE_SUCC) {
- PRINT("PPP register callback failed\r\n");
- zhihui_ppp_deinit();
- return -1;
- }
+ // /* 3. 注册事件回调函数 */
+ // PRINT("Registering PPP event callback...\r\n");
+ // ret = ppp_register_event_callback(ppp_event_callback);
+ // if (ret != ERRCODE_SUCC) {
+ // PRINT("PPP register callback failed\r\n");
+ // zhihui_ppp_deinit();
+ // return -1;
+ // }
g_ppp_env_initialized = true;
PRINT("PPP environment initialized successfully (AT mode)\r\n");
*/
errcode_t ppp_get_connection_info(ppp_connection_info_t *info);
-/**
- * @brief PPP状态重置(从错误状态恢复)
- * @return 错误码
- */
-errcode_t ppp_reset_from_error(void);
-
/* ========== PPP测试接口 ========== */
-/**
- * @brief PPP串口模式切换
- * @param mode 目标模式 ("AT" 或 "PPP")
- * @return 错误码
- */
-errcode_t ppp_test_switch_mode(const char *mode);
/**
* @brief 获取PPP串口状态信息
* @param timeout_ms 超时时间(毫秒)
* @return 错误码
*/
-errcode_t ppp_test_execute_at_command(const char *at_command,
+errcode_t ppp_execute_at_command(const char *at_command,
char *response,
uint32_t response_size,
uint32_t *response_len,
uint32_t timeout_ms);
-/**
- * @brief PPP串口基础功能测试
- * @return 错误码
- */
-errcode_t ppp_test_uart_function(void);
/**
* @brief PPP智能flush测试
* @param uart_bus UART总线号
* @return 错误码
*/
-ppp_error_t ppp_at_handler_init(uint8_t uart_bus);
+ppp_error_t ppp_at_handler_init(uint8_t uart_bus, uint32_t current_baudrate, bool auto_baudrate_mode);
/**
* @brief 反初始化AT命令处理模块
#define SIO_UART_IRQ_NUM UART_0_IRQN // UART IRQ引脚
#endif
-#define PPP_UART_BAUDRATE 1000000
+#define PPP_UART_BAUDRATE 115200
/* 支持的波特率列表(自适应模式) */
#define PPP_BAUDRATE_AUTO_LIST {9600, 57600, 115200}
-#define PPP_BAUDRATE_AUTO_COUNT 4
+#define PPP_BAUDRATE_AUTO_COUNT 3
/* 支持的固定波特率列表 */
#define PPP_BAUDRATE_FIXED_LIST {4800, 9600, 57600, 115200, 230400, 460800, 750000, 921600, 1000000, 2000000, 4000000}
#define PPP_BAUDRATE_FIXED_COUNT 11
/* AT命令配置 */
-#define PPP_AT_CMD_TIMEOUT 5000 // AT命令超时时间(ms)
+#define PPP_AT_CMD_TIMEOUT 3000 // AT命令超时时间(ms)
#define PPP_AT_DEFAULT_TIMEOUT 5000 // AT默认超时时间(ms)
#define PPP_AT_CMD_MAX_LEN 256 // AT命令最大长度
#define PPP_AT_RESPONSE_MAX_LEN 1024 // AT响应最大长度
uint16_t mtu; // MTU大小
} ppp_lwip_network_info_t;
+/* PPP输出统计结构 */
+typedef struct {
+ uint64_t total_packets; // 总输出包数
+ uint64_t total_bytes; // 总输出字节数
+ uint32_t lcp_packets; // LCP包数
+ uint32_t ipcp_packets; // IPCP包数
+ uint32_t ip_packets; // IP包数
+ uint32_t other_packets; // 其他协议包数
+ uint32_t failed_sends; // 发送失败次数
+ uint32_t start_time; // 统计开始时间
+ uint32_t last_packet_time; // 最后一个包的时间
+} ppp_lwip_output_stats_t;
+
/**
* @brief 初始化PPP lwIP集成
* @param config 配置参数
*/
ppp_error_t ppp_lwip_trigger_keepalive(void);
+/**
+ * @brief 获取PPP输出统计信息
+ * @param stats 统计信息结构指针
+ * @return PPP_ERR_OK 成功,其他值失败
+ */
+ppp_error_t ppp_lwip_get_output_stats(ppp_lwip_output_stats_t *stats);
+
#ifdef __cplusplus
}
#endif
+++ /dev/null
-/**
- * @file ppp_performance_config.h
- * @brief PPP性能优化配置
- *
- * 本文件包含针对PPP协商性能问题的优化配置参数
- * 主要解决LCP协商缓慢、Magic Number冲突、超时参数不当等问题
- *
- * 注意:当前这些宏定义主要用作参考和文档说明
- * 实际的优化参数已直接在相关源文件中定义和使用:
- * - ppp_lwip.c: PPP协商超时参数和Magic Number生成
- * - ppp_serial.c: UART通信超时参数
- */
-
-#ifndef PPP_PERFORMANCE_CONFIG_H
-#define PPP_PERFORMANCE_CONFIG_H
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* ================================ PPP协商超时优化 ================================ */
-
-/**
- * @brief PPP FSM超时时间优化 (秒)
- * 默认值: 6秒 -> 优化值: 3秒
- * 说明: 减少LCP/IPCP协商的单次超时时间,提高协商响应速度
- */
-#define PPP_OPTIMIZED_FSM_TIMEOUT 3
-
-/**
- * @brief PPP最大Configure-Request重传次数优化
- * 默认值: 10次 -> 优化值: 6次
- * 说明: 减少不必要的重传,避免过长的协商时间
- */
-#define PPP_OPTIMIZED_MAX_CONF_REQ 6
-
-/**
- * @brief PPP最大NAK循环次数优化
- * 默认值: 5次 -> 优化值: 3次
- * 说明: 减少NAK循环,加快协商收敛
- */
-#define PPP_OPTIMIZED_MAX_NAK_LOOPS 3
-
-/**
- * @brief PPP Terminate-Request重传次数
- * 默认值: 2次 -> 保持: 2次
- * 说明: 连接终止重传次数保持不变
- */
-#define PPP_OPTIMIZED_MAX_TERM_REQ 2
-
-/* ================================ UART通信优化 ================================ */
-
-/**
- * @brief UART写操作超时优化 (毫秒)
- * 默认值: 1000ms -> 优化值: 200ms
- * 说明: 减少UART写操作超时,提高PPP帧传输效率
- */
-#define PPP_OPTIMIZED_UART_WRITE_TIMEOUT 200
-
-/**
- * @brief UART读操作超时优化 (毫秒)
- * 默认值: 200ms -> 优化值: 100ms
- * 说明: 减少PPP数据模式下的读取超时,提高协商响应速度
- */
-#define PPP_OPTIMIZED_UART_READ_TIMEOUT 100
-
-/* ================================ Magic Number优化 ================================ */
-
-/**
- * @brief Magic Number基础种子值
- * 说明: 用于生成唯一Magic Number的基础种子
- */
-#define PPP_MAGIC_NUMBER_SEED 0x12345678
-
-/**
- * @brief Magic Number异或掩码
- * 说明: 增加Magic Number随机性的固定异或值
- */
-#define PPP_MAGIC_NUMBER_XOR_MASK 0xDEADBEEF
-
-/**
- * @brief Magic Number备用值
- * 说明: 当生成的Magic Number为0时使用的备用值
- */
-#define PPP_MAGIC_NUMBER_FALLBACK 0xCAFEBABE
-
-/* ================================ 性能监控配置 ================================ */
-
-/**
- * @brief PPP阶段切换超时阈值 (毫秒)
- * 说明: 超过此时间的阶段切换将被标记为性能问题
- */
-#define PPP_PHASE_TIMEOUT_THRESHOLD 5000
-
-/**
- * @brief PPP协商总超时阈值 (毫秒)
- * 说明: PPP完整协商过程的最大允许时间
- */
-#define PPP_NEGOTIATION_TOTAL_TIMEOUT 30000
-
-/* ================================ 调试配置 ================================ */
-
-/**
- * @brief 启用PPP性能监控
- * 说明: 启用后会监控PPP阶段切换时间和性能指标
- */
-#define PPP_ENABLE_PERFORMANCE_MONITORING 1
-
-/**
- * @brief 启用Magic Number增强随机性
- * 说明: 启用后使用多重随机源生成Magic Number
- */
-#define PPP_ENABLE_ENHANCED_MAGIC_NUMBER 1
-
-/* ================================ 性能优化函数声明 ================================ */
-
-/**
- * @brief 应用PPP性能优化配置
- * @param ppp_pcb PPP控制块指针
- * @return 0成功,非0失败
- */
-int ppp_apply_performance_config(void *ppp_pcb);
-
-/**
- * @brief 生成优化的Magic Number
- * @param base_counter 基础计数器值
- * @param pcb_addr PCB地址用于增加随机性
- * @return 生成的Magic Number
- */
-uint32_t ppp_generate_optimized_magic_number(uint32_t base_counter, void *pcb_addr);
-
-/**
- * @brief 检查PPP性能指标
- * @param phase_duration 阶段持续时间(毫秒)
- * @param phase_id 阶段ID
- * @return 1表示性能正常,0表示性能异常
- */
-int ppp_check_performance_metrics(uint32_t phase_duration, int phase_id);
-
-/* ================================ 性能优化建议 ================================ */
-
-/*
- * PPP协商性能优化建议:
- *
- * 1. Magic Number冲突解决:
- * - 使用多重随机源(时间戳、PCB地址、栈地址)
- * - 避免Magic Number为0
- * - 增加位旋转和异或操作
- *
- * 2. 超时参数优化:
- * - FSM超时从6秒减少到3秒
- * - 最大重传次数从10减少到6
- * - NAK循环从5减少到3
- *
- * 3. UART通信优化:
- * - 写超时从1000ms减少到200ms
- * - 读超时从200ms减少到100ms
- *
- * 4. 性能监控:
- * - 监控阶段切换时间
- * - 检测异常缓慢的协商过程
- * - 提供性能诊断信息
- *
- * 5. 预期效果:
- * - LCP协商时间从30秒减少到5-10秒
- * - 减少Magic Number冲突导致的重协商
- * - 提高整体PPP连接建立速度
- */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* PPP_PERFORMANCE_CONFIG_H */
\ No newline at end of file
*/
ppp_error_t ppp_serial_reset(void);
-/**
- * @brief 测试UART是否正常工作
- * @return 错误码
- */
-ppp_error_t ppp_serial_test_uart(void);
#ifdef __cplusplus
}
// PPP配置参数
static ppp_config_t g_ppp_config = {0};
+// AT通信和波特率标志
+static bool g_at_communication_and_baudrate_flag = false;
+
// 4G电源初始化状态
static bool g_4g_power_initialized = false;
errcode_t ppp_api_get_ppp_netif_name(char* netif_name, uint32_t buffer_size);
+void ppp_check_at_communication_and_baudrate(void);
errcode_t ppp_api_power_init(void)
{
ppp_api_power_init();
- ppp_api_power_control(true);
#define PPP_SERIAL_INIT 1 //外接串口调试模组时,串口要设置input防止干扰。
#if PPP_SERIAL_INIT
+
// 3. UART初始化
- PPP_DEBUG_PRINT("Step 3: Initializing UART for AT mode\n");
+ PPP_DEBUG_PRINT("Step 3: Initializing UART for AT mode baudrate: %d\n", g_ppp_config.baudrate);
ppp_serial_config_t serial_config = {
.uart_bus = SIO_UART_BUS,
.irq_num = SIO_UART_IRQ_NUM,
}
// 初始化AT命令处理器
- ret = ppp_at_handler_init(SIO_UART_BUS);
+ ret = ppp_at_handler_init(SIO_UART_BUS, g_ppp_config.baudrate, true);
if (ret != PPP_ERR_OK) {
PPP_DEBUG_PRINT("Failed to initialize AT handler: %d\n", ret);
ppp_serial_deinit();
} else {
PPP_DEBUG_PRINT("Successfully switched to AT mode\n");
}
-
- // 下达AT指令看是否成功
- ret = ppp_at_test_communication();
- if (ret != PPP_ERR_OK) {
- PPP_DEBUG_PRINT("AT communication test failed: %d\n", ret);
-
- // 4. 串口波特率确认
- PPP_DEBUG_PRINT("Step 4: Confirming UART baudrate\n");
- if (g_ppp_config.auto_baudrate) {
- ret = ppp_at_baudrate_handshake();
- if (ret != PPP_ERR_OK) {
- PPP_DEBUG_PRINT("Baudrate handshake failed: %d\n", ret);
- ppp_at_handler_deinit();
- ppp_serial_deinit();
- goto init_failed;
- }
- PPP_DEBUG_PRINT("Baudrate handshake completed successfully\n");
- }else{
- PPP_DEBUG_PRINT("Baudrate handshake completed successfully\n");
- ppp_at_handler_deinit();
- ppp_serial_deinit();
- goto init_failed;
- }
- } else {
- PPP_DEBUG_PRINT("AT communication test succeeded\n");
- }
#else
ppp_api_leiniao_serial_pin_to_gpio_input();
#endif
- PPP_DEBUG_PRINT("Waiting for modem stabilization after power control...\n");
- // 额外等待时间,让调制解调器完全稳定(特别是在硬件复位后)
- osal_msleep(5000); // 等待5秒让调制解调器完全稳定
-
+
g_ppp_state = PPP_STATE_INITIALIZED;
PPP_DEBUG_PRINT("PPP module initialized successfully\n");
+
+ // 打开4G电源
+ ppp_api_power_control(true);
+ PPP_DEBUG_PRINT("Waiting for modem stabilization after power control...\n");
+ // 等待5秒让调制解调器完全稳定
+ osal_msleep(5000);
+
+ ppp_check_at_communication_and_baudrate();
+
+ ppp_api_update_all_runtime_status();
+
+ ppp_get_network_signal_info();
return ERRCODE_SUCC;
#if PPP_SERIAL_INIT
// ppp_api_power_control(false);
return ERRCODE_FAIL;
}
+void set_at_communication_and_baudrate_flag(bool flag)
+{
+ g_at_communication_and_baudrate_flag = flag;
+}
+bool get_at_communication_and_baudrate_flag(void)
+{
+ return g_at_communication_and_baudrate_flag;
+}
+void ppp_check_at_communication_and_baudrate(void)
+{
+
+ // 用串口读函数读取串口数据,直到没有数据读出,并打印读出来的数据
+ // uint8_t buf[64]={0};
+ // int read_len = 0;
+ // uint32_t start_time = osal_get_jiffies();
+ // do {
+ // read_len = ppp_serial_read(buf, sizeof(buf), 0); // 0表示非阻塞或超时为0
+ // if (read_len > 0) {
+ // // 打印读出来的数据
+ // PPP_DEBUG_PRINT("Read %d bytes from serial: ", read_len);
+ // for (int i = 0; i < read_len; ++i) {
+ // PPP_DEBUG_PRINT("%02X ", buf[i]);
+ // }
+ // PPP_DEBUG_PRINT("\n");
+ // osal_msleep(100);
+ // }
+ // if (osal_get_jiffies() - start_time > 2000) {
+ // break;
+ // }
+ // } while (read_len > 0);
+ // 下达AT指令看是否成功
+ ppp_error_t ret = ppp_at_test_communication();
+ if (ret != PPP_ERR_OK) {
+ PPP_DEBUG_PRINT("AT communication test failed: %d\n", ret);
+ ret = ppp_at_test_communication();
+ if(ret != PPP_ERR_OK) {
+ // 4. 串口波特率确认
+ PPP_DEBUG_PRINT("Step 4: Confirming UART baudrate\n");
+ if (g_ppp_config.auto_baudrate) {
+ ret = ppp_at_baudrate_handshake();
+ if (ret != PPP_ERR_OK) {
+ PPP_DEBUG_PRINT("Baudrate handshake failed: %d\n", ret);
+ goto init_failed;
+ }
+ PPP_DEBUG_PRINT("Baudrate handshake completed successfully\n");
+ }else{
+ PPP_DEBUG_PRINT("Baudrate handshake completed successfully\n");
+ goto init_failed;
+ }
+ }
+ } else {
+ PPP_DEBUG_PRINT("AT communication test succeeded\n");
+ }
+ set_at_communication_and_baudrate_flag(true);
+ return ;
+init_failed:
+ set_at_communication_and_baudrate_flag(false);
+}
+
+
static void ppp_lwip_event_callback(const ppp_lwip_event_t *event, void *arg)
{
// 6. 重新初始化AT处理器
PPP_DEBUG_INFO("Reinitializing AT handler...");
- ret = ppp_at_handler_init(SIO_UART_BUS); // 使用UART bus 0
+ ret = ppp_at_handler_init(SIO_UART_BUS, g_ppp_config.baudrate, true); // 使用UART bus 0
if (ret != PPP_ERR_OK) {
PPP_DEBUG_ERROR("Failed to reinitialize AT handler: %d", ret);
return ERRCODE_FAIL;
// 6. 重新初始化AT处理器
PPP_DEBUG_INFO("Reinitializing AT handler...");
- ret = ppp_at_handler_init(SIO_UART_BUS); // 使用UART bus 0
+ ret = ppp_at_handler_init(SIO_UART_BUS, g_ppp_config.baudrate, true); // 使用UART bus 0
if (ret != PPP_ERR_OK) {
PPP_DEBUG_ERROR("Failed to reinitialize AT handler: %d", ret);
return ret;
return ERRCODE_SUCC;
}
-/**
- * @brief PPP状态重置(从错误状态恢复)
- */
-errcode_t ppp_reset_from_error(void)
-{
- if (g_ppp_state != PPP_STATE_ERROR) {
- PPP_DEBUG_PRINT("PPP reset: not in error state, current state: %d\n", g_ppp_state);
- return ERRCODE_SUCC;
- }
-
- PPP_DEBUG_PRINT("Resetting PPP from error state\n");
-
- // 1. 停止所有可能的活动
- ppp_lwip_stop_receive_thread();
- ppp_lwip_deinit();
-
- // 2. 尝试恢复到AT模式
- ppp_error_t ret = ppp_serial_switch_to_at_mode();
- if (ret == PPP_ERR_OK) {
- // 3. 重新初始化AT处理器
- ret = ppp_at_handler_init(SIO_UART_BUS);
- if (ret == PPP_ERR_OK) {
- g_ppp_state = PPP_STATE_INITIALIZED;
- PPP_DEBUG_PRINT("PPP successfully reset to INITIALIZED state\n");
- return ERRCODE_SUCC;
- } else {
- PPP_DEBUG_ERROR("Failed to reinitialize AT handler during reset\n");
- }
- } else {
- PPP_DEBUG_ERROR("Failed to switch to AT mode during reset\n");
- }
-
- // 如果恢复失败,保持错误状态
- PPP_DEBUG_ERROR("PPP reset failed, remains in error state\n");
- return ERRCODE_FAIL;
-}
-
/**
* @brief PPP模块去初始化
*/
/* ========== PPP测试接口实现 ========== */
-/**
- * @brief PPP串口模式切换
- */
-errcode_t ppp_test_switch_mode(const char *mode)
-{
- if (mode == NULL) {
- return ERRCODE_INVALID_PARAM;
- }
-
- ppp_error_t ret;
- if (strcmp(mode, "AT") == 0) {
- ret = ppp_serial_switch_to_at_mode();
- } else if (strcmp(mode, "PPP") == 0) {
- ret = ppp_serial_switch_to_ppp_mode();
- } else {
- return ERRCODE_INVALID_PARAM;
- }
-
- return (ret == PPP_ERR_OK) ? ERRCODE_SUCC : ERRCODE_FAIL;
-}
/**
* @brief 执行AT指令透传
*/
-errcode_t ppp_test_execute_at_command(const char *at_command,
+errcode_t ppp_execute_at_command(const char *at_command,
char *response,
uint32_t response_size,
uint32_t *response_len,
}
}
-/**
- * @brief PPP串口基础功能测试
- */
-errcode_t ppp_test_uart_function(void)
-{
- ppp_error_t ret = ppp_serial_test_uart();
- return (ret == PPP_ERR_OK) ? ERRCODE_SUCC : ERRCODE_FAIL;
-}
+
/**
* @brief PPP智能flush测试
errcode_t ppp_api_update_imei(void)
{
// 检查是否在AT模式
- if (ppp_serial_get_mode() != PPP_SERIAL_MODE_AT) {
+ if (ppp_serial_get_mode() != PPP_SERIAL_MODE_AT || !get_at_communication_and_baudrate_flag()) {
PPP_DEBUG_WARN("Cannot update IMEI: not in AT mode (current mode: %d)", ppp_serial_get_mode());
return ERRCODE_FAIL;
}
char imei_temp[32] = {0};
// 使用现有的AT命令执行接口
- errcode_t ret = ppp_test_execute_at_command("AT+CGSN", response, 512, &response_len, 1000);
+ errcode_t ret = ppp_execute_at_command("AT+CGSN", response, 512, &response_len, 1000);
if (ret != ERRCODE_SUCC) {
PPP_DEBUG_ERROR("Failed to send AT+CGSN command");
free(response);
errcode_t ppp_api_update_signal(void)
{
// 检查是否在AT模式
- if (ppp_serial_get_mode() != PPP_SERIAL_MODE_AT) {
+ if (ppp_serial_get_mode() != PPP_SERIAL_MODE_AT || !get_at_communication_and_baudrate_flag()) {
PPP_DEBUG_WARN("Cannot update signal: not in AT mode (current mode: %d)", ppp_serial_get_mode());
return ERRCODE_FAIL;
}
int signal = 99; // 默认无信号
// 使用现有的AT命令执行接口
- errcode_t ret = ppp_test_execute_at_command("AT+CSQ", response, 512, &response_len, 1000);
+ errcode_t ret = ppp_execute_at_command("AT+CSQ", response, 512, &response_len, 1000);
if (ret != ERRCODE_SUCC) {
PPP_DEBUG_ERROR("Failed to send AT+CSQ command");
free(response);
errcode_t ppp_api_update_operator(void)
{
// 检查是否在AT模式
- if (ppp_serial_get_mode() != PPP_SERIAL_MODE_AT) {
+ if (ppp_serial_get_mode() != PPP_SERIAL_MODE_AT || !get_at_communication_and_baudrate_flag()) {
PPP_DEBUG_WARN("Cannot update operator: not in AT mode (current mode: %d)", ppp_serial_get_mode());
return ERRCODE_FAIL;
}
char operator_temp[64] = {0};
// 使用现有的AT命令执行接口
- errcode_t ret = ppp_test_execute_at_command("AT+COPS?", response, 512, &response_len, 10000);
+ errcode_t ret = ppp_execute_at_command("AT+COPS?", response, 512, &response_len, 10000);
if (ret != ERRCODE_SUCC) {
PPP_DEBUG_ERROR("Failed to send AT+COPS command");
free(response);
errcode_t ppp_api_update_iccid(void)
{
// 检查是否在AT模式
- if (ppp_serial_get_mode() != PPP_SERIAL_MODE_AT) {
+ if (ppp_serial_get_mode() != PPP_SERIAL_MODE_AT || !get_at_communication_and_baudrate_flag()) {
PPP_DEBUG_WARN("Cannot update ICCID: not in AT mode (current mode: %d)", ppp_serial_get_mode());
return ERRCODE_FAIL;
}
char iccid_temp[32] = {0};
// 使用现有的AT命令执行接口
- errcode_t ret = ppp_test_execute_at_command("AT+CCID", response, 512, &response_len, 5000);
+ errcode_t ret = ppp_execute_at_command("AT+CCID", response, 512, &response_len, 5000);
if (ret != ERRCODE_SUCC) {
PPP_DEBUG_ERROR("Failed to send AT+CCID command");
free(response);
errcode_t ppp_api_update_version(void)
{
// 检查是否在AT模式
- if (ppp_serial_get_mode() != PPP_SERIAL_MODE_AT) {
+ if (ppp_serial_get_mode() != PPP_SERIAL_MODE_AT || !get_at_communication_and_baudrate_flag()) {
PPP_DEBUG_WARN("Cannot update version: not in AT mode (current mode: %d)", ppp_serial_get_mode());
return ERRCODE_FAIL;
}
char version_temp[64] = {0};
// 使用现有的AT命令执行接口
- errcode_t ret = ppp_test_execute_at_command("AT+GMR", response, 512, &response_len, 5000);
+ errcode_t ret = ppp_execute_at_command("AT+GMR", response, 512, &response_len, 5000);
if (ret != ERRCODE_SUCC) {
PPP_DEBUG_ERROR("Failed to send AT+GMR command");
free(response);
errcode_t ppp_api_update_network_status(void)
{
// 检查是否在AT模式
- if (ppp_serial_get_mode() != PPP_SERIAL_MODE_AT) {
+ if (ppp_serial_get_mode() != PPP_SERIAL_MODE_AT || !get_at_communication_and_baudrate_flag()) {
PPP_DEBUG_WARN("Cannot update network status: not in AT mode (current mode: %d)", ppp_serial_get_mode());
return ERRCODE_FAIL;
}
errcode_t ret;
// 先尝试AT+CREG
- ret = ppp_test_execute_at_command("AT+CREG?", response, 512, &response_len, 5000);
+ ret = ppp_execute_at_command("AT+CREG?", response, 512, &response_len, 5000);
if (ret == ERRCODE_SUCC) {
ret = ppp_parse_network_status_response(response, &network_status);
if (ret == ERRCODE_SUCC) {
}
// 如果CREG失败,尝试AT+CEREG
- ret = ppp_test_execute_at_command("AT+CEREG?", response, 512, &response_len, 5000);
+ ret = ppp_execute_at_command("AT+CEREG?", response, 512, &response_len, 5000);
if (ret != ERRCODE_SUCC) {
PPP_DEBUG_ERROR("Failed to send AT+CEREG command");
free(response);
errcode_t ppp_api_update_sim_status(void)
{
// 检查是否在AT模式
- if (ppp_serial_get_mode() != PPP_SERIAL_MODE_AT) {
+ if (ppp_serial_get_mode() != PPP_SERIAL_MODE_AT || !get_at_communication_and_baudrate_flag()) {
PPP_DEBUG_WARN("Cannot update SIM status: not in AT mode (current mode: %d)", ppp_serial_get_mode());
return ERRCODE_FAIL;
}
uint32_t response_len;
// 通过AT+CCID命令检查SIM卡状态
- errcode_t ret = ppp_test_execute_at_command("AT+CCID", response, 512, &response_len, 1000);
+ errcode_t ret = ppp_execute_at_command("AT+CCID", response, 512, &response_len, 1000);
if (ret != ERRCODE_SUCC) {
// 如果CCID命令失败,说明SIM卡可能未插入或有问题
cat1_api_runtime_set_cat1_simstat(0); // 0表示SIM卡异常
/**
* @brief 初始化AT命令处理模块
*/
-ppp_error_t ppp_at_handler_init(uint8_t uart_bus)
+ppp_error_t ppp_at_handler_init(uint8_t uart_bus, uint32_t current_baudrate, bool auto_baudrate_mode)
{
if (g_at_ctx.initialized) {
PPP_DEBUG_WARN("AT handler already initialized");
}
g_at_ctx.uart_bus = uart_bus;
- g_at_ctx.current_baudrate = PPP_UART_BAUDRATE;
- g_at_ctx.auto_baudrate_mode = true;
+ g_at_ctx.current_baudrate = current_baudrate;
+ g_at_ctx.auto_baudrate_mode = auto_baudrate_mode;
/* 创建互斥锁 */
if (osal_mutex_init(&g_at_ctx.at_mutex) != OSAL_SUCCESS) {
// 3次重试AT
ppp_error_t ret = PPP_ERR_AT_FAILED;
- for (int retry = 0; retry < 3; retry++) {
+ for (int retry = 0; retry < 2; retry++) {
PPP_DEBUG_DEBUG("--- AT Test at %u baud, retry %d/3 ---", baudrate, retry + 1);
// 再次清空缓冲区,防止上次残留
while (uapi_uart_read(g_at_ctx.uart_bus, dummy_buffer, sizeof(dummy_buffer), 100) > 0) {}
ppp_at_response_t response;
- ret = ppp_at_send_command("AT", "OK", 3000, &response);
+ ret = ppp_at_send_command("AT", "OK", 1000, &response);
if (ret == PPP_ERR_OK) {
PPP_DEBUG_INFO("AT command successful at baudrate %u", baudrate);
// 在当前波特率下,设置AT+IPR=1000000
- char ipr_cmd[32];
- snprintf_s(ipr_cmd, sizeof(ipr_cmd), sizeof(ipr_cmd) - 1, "AT+IPR=1000000");
- PPP_DEBUG_DEBUG("Setting module baudrate to 1000000 with: %s", ipr_cmd);
-
- ppp_at_response_t ipr_response;
- ppp_error_t ipr_ret = ppp_at_send_command(ipr_cmd, "OK", 3000, &ipr_response);
- if (ipr_ret != PPP_ERR_OK) {
- PPP_DEBUG_ERROR("Failed to set module baudrate to 1000000 (AT+IPR)");
- return PPP_ERR_AT_FAILED;
- }
-
ppp_at_set_baudrate(PPP_UART_BAUDRATE);
// 再次reset模组,让其自动工作在1000000波特率下
- PPP_DEBUG_DEBUG("Resetting module again to switch to 1000000 baudrate...");
+ PPP_DEBUG_DEBUG("Resetting module again to switch to baudrate %d...",PPP_UART_BAUDRATE);
ppp_power_reset_cat1();
osal_msleep(5000);
- PPP_DEBUG_INFO("Baudrate handshake successful, now at 1000000 baud");
+ ret = ppp_at_send_command("AT", "OK", 1000, &response);
+ if(ret != PPP_ERR_OK) {
+ PPP_DEBUG_INFO("Baudrate handshake failed, now at %d baud",PPP_UART_BAUDRATE);
+ }else{
+ PPP_DEBUG_INFO("Baudrate handshake successful, now at %d baud",PPP_UART_BAUDRATE);
+ }
return PPP_ERR_OK;
} else {
PPP_DEBUG_WARN("AT command failed at baudrate %u, retry %d/3 (error: %d)", baudrate, retry + 1, ret);
return PPP_ERR_INVALID_PARAM;
}
+ /* 防止系统卡死的安全措施 */
+ const uint32_t MAX_COMMAND_TIMEOUT = 60000; // 绝对最大超时时间60秒
+ if (timeout > MAX_COMMAND_TIMEOUT) {
+ PPP_DEBUG_WARN("Command timeout %u ms exceeds maximum %u ms, capping it",
+ timeout, MAX_COMMAND_TIMEOUT);
+ timeout = MAX_COMMAND_TIMEOUT;
+ }
+
PPP_DEBUG_CRITICAL("Step 1: Attempting to acquire AT mutex...");
uint32_t mutex_start = (uint32_t)osal_get_jiffies();
- osal_mutex_lock(&g_at_ctx.at_mutex);
+
+ /* 使用带超时的互斥锁获取,防止永久阻塞 */
+ int mutex_result = osal_mutex_lock_timeout(&g_at_ctx.at_mutex, timeout + 5000);
+ if (mutex_result != OSAL_SUCCESS) {
+ PPP_DEBUG_ERROR("Failed to acquire AT mutex within timeout, this indicates a serious problem");
+ PPP_DEBUG_ERROR("Possible causes: 1) Previous AT command hung 2) Mutex corruption 3) Deadlock");
+ return PPP_ERR_TIMEOUT;
+ }
+
uint32_t mutex_end = (uint32_t)osal_get_jiffies();
PPP_DEBUG_CRITICAL("Step 1: AT mutex acquired in %u ms", osal_jiffies_to_msecs(mutex_end - mutex_start));
PPP_DEBUG_INFO("Echo disabled successfully");
}
+ ret = ppp_at_send_command("AT+NVETOSUPERDS=A,1", "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");
+ }
// 发送一个简单的AT命令确认调制解调器状态
ret = ppp_at_send_command("AT", "OK", 3000, &response);
// 再次拨号
PPP_DEBUG_INFO("Re-dialing to ensure proper PPP mode...");
- ret = ppp_at_send_command("ATD*99***2#", "CONNECT", 30000, &response);
+ ret = ppp_at_send_command("ATD*99***2#", "CONNECT", 5000, &response);
if (ret != PPP_ERR_OK) {
PPP_DEBUG_ERROR("Re-dial failed");
return ret;
ppp_at_response_t response;
// 发送简单的AT命令测试通信
- ppp_error_t ret = ppp_at_send_command("AT", "OK", 3000, &response);
+ ppp_error_t ret = ppp_at_send_command("AT", "OK", 1000, &response);
if (ret == PPP_ERR_OK) {
PPP_DEBUG_INFO("AT communication test passed");
} else {
/* 内部函数实现 */
+/**
+ * @brief 检查AT响应是否完整
+ * @param buffer 响应缓冲区
+ * @param length 缓冲区长度
+ * @return true 如果响应完整,false 否则
+ */
+static bool ppp_at_check_response_complete(const char *buffer, uint32_t length)
+{
+ if (!buffer || length == 0) {
+ return false;
+ }
+
+ /* 搜索OK终止符 */
+ for (uint32_t i = 0; i <= length - 2; i++) {
+ if (buffer[i] == 'O' && buffer[i+1] == 'K') {
+ /* 检查OK前面是否有换行符(避免误匹配) */
+ if (i == 0 || buffer[i-1] == '\n' || buffer[i-1] == '\r') {
+ PPP_DEBUG_DEBUG("Found OK terminator at position %u", i);
+ return true;
+ }
+ }
+ }
+
+ /* 搜索ERROR终止符 */
+ if (length >= 5) {
+ for (uint32_t i = 0; i <= length - 5; i++) {
+ if (strncmp(&buffer[i], "ERROR", 5) == 0) {
+ /* 检查ERROR前面是否有换行符 */
+ if (i == 0 || buffer[i-1] == '\n' || buffer[i-1] == '\r') {
+ PPP_DEBUG_DEBUG("Found ERROR terminator at position %u", i);
+ return true;
+ }
+ }
+ }
+ }
+
+ /* 检查其他终止符 */
+ if (strstr(buffer, "CONNECT") ||
+ strstr(buffer, "NO CARRIER") ||
+ strstr(buffer, "BUSY") ||
+ strstr(buffer, "NO DIALTONE") ||
+ strstr(buffer, "+CME ERROR") ||
+ strstr(buffer, "+CMS ERROR")) {
+ PPP_DEBUG_DEBUG("Found other terminator in response");
+ return true;
+ }
+
+ return false;
+}
+
/**
* @brief 解析AT命令响应
*/
bool has_data = false;
uint32_t read_attempts = 0;
+ /* 防止卡死的安全措施 */
+ const uint32_t MAX_READ_ATTEMPTS = 1000; // 最大尝试次数
+ const uint32_t ABSOLUTE_TIMEOUT_MS = timeout + 5000; // 绝对超时时间(比预期超时多5秒)
+ const uint32_t UART_READ_TIMEOUT_MS = 50; // UART读取超时
+
/* 清空全局缓存 */
memset(g_at_response_buffer, 0, g_at_buffer_size);
- PPP_DEBUG_CRITICAL("WAIT_RESPONSE: Starting direct UART read (timeout: %u ms, buffer_size: %u)",
- timeout, g_at_buffer_size);
+ PPP_DEBUG_CRITICAL("WAIT_RESPONSE: Starting direct UART read (timeout: %u ms, absolute_timeout: %u ms, buffer_size: %u)",
+ timeout, ABSOLUTE_TIMEOUT_MS, g_at_buffer_size);
/* 循环读取直到找到响应结论或超时 */
while (!response_complete) {
read_attempts, elapsed, has_data, bytes_received);
}
- /* 检查超时条件:如果没有数据且达到超时时间,退出 */
+ /* 绝对超时检查 - 防止无限循环 */
+ if (elapsed >= ABSOLUTE_TIMEOUT_MS) {
+ PPP_DEBUG_ERROR("WAIT_RESPONSE: ABSOLUTE TIMEOUT - forced exit after %u ms (attempts: %u)",
+ elapsed, read_attempts);
+ PPP_DEBUG_ERROR("WAIT_RESPONSE: This prevents system hang, but indicates a serious problem");
+ break;
+ }
+
+ /* 最大尝试次数检查 - 防止无限循环 */
+ if (read_attempts >= MAX_READ_ATTEMPTS) {
+ PPP_DEBUG_ERROR("WAIT_RESPONSE: MAX ATTEMPTS REACHED - forced exit after %u attempts (elapsed: %u ms)",
+ read_attempts, elapsed);
+ PPP_DEBUG_ERROR("WAIT_RESPONSE: This prevents system hang, but indicates a serious problem");
+ break;
+ }
+
+ /* 正常超时条件:如果没有数据且达到预期超时时间,退出 */
if (!has_data && elapsed >= timeout) {
- PPP_DEBUG_CRITICAL("WAIT_RESPONSE: TIMEOUT - no data received after %u ms (attempts: %u)", elapsed, read_attempts);
+ PPP_DEBUG_CRITICAL("WAIT_RESPONSE: NORMAL TIMEOUT - no data received after %u ms (attempts: %u)",
+ elapsed, read_attempts);
+ break;
+ }
+
+ /* 如果已有数据但超过预期超时时间很多,也要退出 */
+ if (has_data && elapsed >= (timeout + 2000)) {
+ PPP_DEBUG_WARN("WAIT_RESPONSE: EXTENDED TIMEOUT - has data but taking too long (%u ms, attempts: %u)",
+ elapsed, read_attempts);
break;
}
int32_t ret = uapi_uart_read(g_at_ctx.uart_bus,
g_at_response_buffer + bytes_received,
g_at_buffer_size - bytes_received - 1,
- 50); /* 50ms读取超时 */
+ UART_READ_TIMEOUT_MS);
uint32_t uart_read_end = (uint32_t)osal_get_jiffies();
uint32_t uart_read_time = osal_jiffies_to_msecs(uart_read_end - uart_read_start);
if (ret > 0) {
has_data = true;
bytes_received += (uint32_t)ret;
+
+ /* 防止缓冲区溢出 */
+ if (bytes_received >= g_at_buffer_size - 1) {
+ PPP_DEBUG_ERROR("WAIT_RESPONSE: Buffer overflow protection - truncating at %u bytes", bytes_received);
+ bytes_received = g_at_buffer_size - 1;
+ g_at_response_buffer[bytes_received] = '\0';
+ break;
+ }
+
g_at_response_buffer[bytes_received] = '\0';
PPP_DEBUG_CRITICAL("WAIT_RESPONSE: Read %d bytes, total: %u bytes", ret, bytes_received);
/* 打印接收到的原始数据(十六进制) */
PPP_DEBUG_DEBUG("WAIT_RESPONSE: Raw data received:");
- for (int i = bytes_received - ret; i < bytes_received; i++) {
+ for (int i = bytes_received - ret; i < (int)bytes_received; i++) {
PPP_DEBUG_PRINT("%02X ", g_at_response_buffer[i]);
+ if ((i + 1) % 16 == 0) PPP_DEBUG_PRINT("\n");
}
- PPP_DEBUG_PRINT("\n");
+ if (ret % 16 != 0) PPP_DEBUG_PRINT("\n");
- /* 检查缓存中是否有需要检测的结论 */
- PPP_DEBUG_DEBUG("WAIT_RESPONSE: Checking for terminators...");
- bool found_terminator = false;
-
- /* 搜索OK终止符 */
- PPP_DEBUG_DEBUG("WAIT_RESPONSE: Searching for OK terminator...");
- for (uint32_t i = 0; i <= bytes_received - 2; i++) {
- if (g_at_response_buffer[i] == 'O' && g_at_response_buffer[i+1] == 'K') {
- /* 检查OK前面是否有换行符(避免误匹配) */
- if (i == 0 || g_at_response_buffer[i-1] == '\n' || g_at_response_buffer[i-1] == '\r') {
- PPP_DEBUG_CRITICAL("WAIT_RESPONSE: Found OK terminator at position %u", i);
- found_terminator = true;
- response_complete = true;
- break;
- }
- }
+ /* 检查是否收到完整响应 */
+ if (ppp_at_check_response_complete((char*)g_at_response_buffer, bytes_received)) {
+ PPP_DEBUG_CRITICAL("WAIT_RESPONSE: Complete response detected");
+ response_complete = true;
}
- /* 搜索ERROR终止符 */
- if (!found_terminator && bytes_received >= 5) {
- PPP_DEBUG_DEBUG("WAIT_RESPONSE: Searching for ERROR terminator...");
- for (uint32_t i = 0; i <= bytes_received - 5; i++) {
- if (strncmp((char*)&g_at_response_buffer[i], "ERROR", 5) == 0) {
- /* 检查ERROR前面是否有换行符 */
- if (i == 0 || g_at_response_buffer[i-1] == '\n' || g_at_response_buffer[i-1] == '\r') {
- PPP_DEBUG_CRITICAL("WAIT_RESPONSE: Found ERROR terminator at position %u", i);
- found_terminator = true;
- response_complete = true;
- break;
- }
- }
- }
- }
+ /* 重置超时计时器,因为我们收到了数据 */
+ start_time = current_time;
- /* 检查其他终止符 */
- if (!found_terminator) {
- PPP_DEBUG_DEBUG("WAIT_RESPONSE: Searching for other terminators...");
- char *buffer_str = (char*)g_at_response_buffer;
- if (strstr(buffer_str, "CONNECT") ||
- strstr(buffer_str, "NO CARRIER") ||
- strstr(buffer_str, "BUSY") ||
- strstr(buffer_str, "NO DIALTONE")) {
- PPP_DEBUG_CRITICAL("WAIT_RESPONSE: Found other terminator in response");
- found_terminator = true;
- response_complete = true;
- }
- }
+ } else if (ret == 0) {
+ /* 没有数据,继续等待 */
+ PPP_DEBUG_DEBUG("WAIT_RESPONSE: No data available, continuing...");
- /* 检查缓存是否已满 */
- if (bytes_received >= g_at_buffer_size - 1) {
- PPP_DEBUG_WARN("AT response buffer full, stopping read");
- response_complete = true;
- }
+ /* 短暂延迟以避免CPU占用过高 */
+ osal_msleep(10);
- } else if (ret == 0) {
- /* 没有读到数据 */
- if (has_data) {
- /* 已经有数据了,继续尝试读取更多数据,但不受严格超时限制 */
- PPP_DEBUG_DEBUG("No new data, but continuing due to existing data");
- osal_msleep(10); /* 短暂延时后继续 */
- } else {
- /* 还没有任何数据,检查是否超时 */
- if (elapsed >= timeout) {
- PPP_DEBUG_WARN("No data received within timeout");
- break;
+ } else {
+ /* UART读取错误 */
+ PPP_DEBUG_ERROR("WAIT_RESPONSE: UART read error: %d", ret);
+
+ /* UART错误时短暂延迟后继续,但不重置超时 */
+ osal_msleep(50);
+ }
+
+ /* 检查是否收到了足够的数据但没有完整响应标志 */
+ if (has_data && bytes_received > 0) {
+ /* 如果收到数据但等待时间过长,可能需要强制结束 */
+ uint32_t data_wait_time = osal_jiffies_to_msecs(current_time - start_time);
+ if (data_wait_time > 1000) { // 收到数据后等待1秒仍无完整响应
+ PPP_DEBUG_WARN("WAIT_RESPONSE: Long wait after receiving data (%u ms), checking for partial response",
+ data_wait_time);
+
+ /* 检查是否至少包含一些有用的响应内容 */
+ if (bytes_received >= 2) { // 至少有一些内容
+ PPP_DEBUG_WARN("WAIT_RESPONSE: Accepting partial response to prevent hang");
+ response_complete = true;
}
- osal_msleep(10); /* 短暂延时后继续 */
}
- } else {
- PPP_DEBUG_ERROR("UART read error: %d", ret);
- break;
}
}
if (!g_at_ctx.initialized || !info) {
return PPP_ERR_INVALID_PARAM;
}
-
+ if(!get_at_communication_and_baudrate_flag())
+ {
+ PPP_DEBUG_ERROR("AT communication and baudrate failed");
+ return PPP_ERR_AT_FAILED;
+ }
PPP_DEBUG_INFO("Getting network signal information (AT+CESQ)...");
ppp_at_response_t response;
uint8_t cat1_network_type;
int sim;
int signal;
+ int rsrp;
+ int rsrq;
char opera[64];
char imei[32];
char pyVer[32];
char modemVer[64];
} ppp_cat1_runtime_status_t;
+typedef struct {
+ int rsrp;
+ int rsrq;
+} ppp_cat1_signal_info_t;
+
// PPP模块的运行时状态
static ppp_cat1_runtime_status_t g_ppp_runtime = {0};
static bool g_ppp_monitor_enabled = false;
static uint32_t g_last_data_activity_time = 0;
static uint32_t g_connection_idle_timeout = 60000; /* 60秒无数据活动后检查连接 */
+
+/* PPP输出统计结构 */
+typedef struct {
+ uint64_t total_packets; // 总输出包数
+ uint64_t total_bytes; // 总输出字节数
+ uint32_t lcp_packets; // LCP包数
+ uint32_t ipcp_packets; // IPCP包数
+ uint32_t ip_packets; // IP包数
+ uint32_t other_packets; // 其他协议包数
+ uint32_t failed_sends; // 发送失败次数
+ uint32_t start_time; // 统计开始时间
+ uint32_t last_packet_time; // 最后一个包的时间
+} ppp_output_stats_t;
+
+static ppp_output_stats_t g_ppp_output_stats = {0};
/* 内部函数声明 */
static u32_t ppp_lwip_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx);
static void ppp_lwip_link_status_callback(ppp_pcb *pcb, int err_code, void *ctx);
/* 函数前向声明 */
static void ppp_lwip_print_mru_status(void);
+static void ppp_lwip_reset_output_stats(void);
+static void ppp_lwip_update_output_stats(uint16_t protocol, uint32_t bytes, bool success);
/**
* @brief 记录数据活动时间
g_lwip_ctx.event_callback_arg = config->event_callback_arg;
g_lwip_ctx.initialized = true;
+
+ /* 重置输出统计 */
+ ppp_lwip_reset_output_stats();
+
PPP_DEBUG_INFO("PPP lwIP integration initialized");
return PPP_ERR_OK;
/* 记录数据活动 */
ppp_lwip_record_data_activity();
+ /* 解析协议类型用于统计 */
+ uint16_t protocol = 0;
+ if (len >= 4) {
+ uint32_t offset = 0;
+ if (data[0] == 0x7E) {
+ offset = 1;
+ }
+ if (offset + 3 < len && data[offset] == 0xFF && data[offset + 1] == 0x03) {
+ offset += 2;
+ if (offset + 1 < len) {
+ protocol = (data[offset] << 8) | data[offset + 1];
+ }
+ }
+ }
+
/* 发送PPP协议输出日志 */
PPP_DEBUG_PRINT("=== PPP Protocol Output ===\n");
PPP_DEBUG_PRINT("PPP TX: %u bytes\n", 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");
+
+ /* 更新失败统计 */
+ ppp_lwip_update_output_stats(protocol, len, false);
return 0;
}
PPP_DEBUG_PRINT("=== PPP Output SUCCESS ===\n");
+
+ /* 更新成功统计 */
+ ppp_lwip_update_output_stats(protocol, len, true);
+
return len;
}
}
}
+/**
+ * @brief 重置PPP输出统计
+ */
+static void ppp_lwip_reset_output_stats(void)
+{
+ memset_s(&g_ppp_output_stats, sizeof(g_ppp_output_stats), 0, sizeof(g_ppp_output_stats));
+ g_ppp_output_stats.start_time = ppp_lwip_get_time_ms();
+}
+
+/**
+ * @brief 更新PPP输出统计
+ * @param protocol PPP协议类型
+ * @param bytes 字节数
+ * @param success 是否发送成功
+ */
+static void ppp_lwip_update_output_stats(uint16_t protocol, uint32_t bytes, bool success)
+{
+ if (success) {
+ g_ppp_output_stats.total_packets++;
+ g_ppp_output_stats.total_bytes += bytes;
+ g_ppp_output_stats.last_packet_time = ppp_lwip_get_time_ms();
+
+ // 根据协议类型更新计数
+ switch (protocol) {
+ case 0xC021: // LCP
+ g_ppp_output_stats.lcp_packets++;
+ break;
+ case 0x8021: // IPCP
+ g_ppp_output_stats.ipcp_packets++;
+ break;
+ case 0x0021: // IP
+ g_ppp_output_stats.ip_packets++;
+ break;
+ default:
+ g_ppp_output_stats.other_packets++;
+ break;
+ }
+ } else {
+ g_ppp_output_stats.failed_sends++;
+ }
+}
+
+/**
+ * @brief 获取PPP输出统计信息
+ * @param stats 统计信息结构指针
+ * @return PPP_ERR_OK 成功,其他值失败
+ */
+ppp_error_t ppp_lwip_get_output_stats(ppp_lwip_output_stats_t *stats)
+{
+ if (!stats) {
+ return PPP_ERR_INVALID_PARAM;
+ }
+
+ memcpy_s(stats, sizeof(ppp_lwip_output_stats_t), &g_ppp_output_stats, sizeof(ppp_output_stats_t));
+ return PPP_ERR_OK;
+}
+
#endif /* LWIP_PPP_SUPPORT */
\ No newline at end of file
/* 配置参数 - 降级为DEBUG级别 */
PPP_DEBUG_DEBUG("Configuration parameters:");
- PPP_DEBUG_DEBUG(" - UART Bus: %u", config->uart_bus);
+ PPP_DEBUG_INFO(" - UART Bus: %u", config->uart_bus);
PPP_DEBUG_DEBUG(" - IRQ Num: %u", config->irq_num);
- PPP_DEBUG_DEBUG(" - Baudrate: %u", config->baudrate);
+ PPP_DEBUG_INFO(" - Baudrate: %u", config->baudrate);
PPP_DEBUG_DEBUG(" - TX Pin: %u", config->tx_pin);
PPP_DEBUG_DEBUG(" - RX Pin: %u", config->rx_pin);
PPP_DEBUG_DEBUG(" - RX Buffer Size: %u bytes", config->rx_buffer_size);
/* 初始化UART */
PPP_DEBUG_DEBUG("Calling uapi_uart_init...");
- errcode_t ret = uapi_uart_init(g_serial_ctx.uart_bus,
- &g_serial_ctx.pin_config,
- &g_serial_ctx.uart_attr,
- NULL,
- &g_serial_ctx.buffer_config);
+ // errcode_t ret = uapi_uart_init(g_serial_ctx.uart_bus,
+ // &g_serial_ctx.pin_config,
+ // &g_serial_ctx.uart_attr,
+ // NULL,
+ // &g_serial_ctx.buffer_config);
+ errcode_t ret = uapi_uart_set_attr(g_serial_ctx.uart_bus, &g_serial_ctx.uart_attr);
if (ret != ERRCODE_SUCC) {
PPP_DEBUG_ERROR("Failed to initialize UART: error code = %d (0x%x)", ret, ret);
PPP_DEBUG_ERROR("UART init failed with bus=%u, tx_pin=%u, rx_pin=%u, baudrate=%u",
osal_mutex_destroy(&g_serial_ctx.tx_mutex);
return PPP_ERR_UART;
}
+
PPP_DEBUG_INFO("UART initialized successfully (error code = %d)", ret);
/* 创建同步对象 */
return PPP_ERR_OK;
}
-/**
- * @brief 测试UART是否正常工作
- */
-ppp_error_t ppp_serial_test_uart(void)
-{
- if (!g_serial_ctx.initialized) {
- PPP_DEBUG_ERROR("PPP serial not initialized");
- return PPP_ERR_INVALID_PARAM;
- }
-
- PPP_DEBUG_INFO("=== UART Test Start ===");
- PPP_DEBUG_INFO("Current state:");
- PPP_DEBUG_INFO(" - Initialized: %s", g_serial_ctx.initialized ? "true" : "false");
- PPP_DEBUG_INFO(" - Mode: %d", g_serial_ctx.current_mode);
- PPP_DEBUG_INFO(" - UART Bus: %u", g_serial_ctx.uart_bus);
- PPP_DEBUG_INFO(" - TX Pin: %u", g_serial_ctx.pin_config.tx_pin);
- PPP_DEBUG_INFO(" - RX Pin: %u", g_serial_ctx.pin_config.rx_pin);
- PPP_DEBUG_INFO(" - Baudrate: %u", g_serial_ctx.uart_attr.baud_rate);
-
- /* 发送测试字符串 */
- const char *test_msg = "AT\r\n";
- uint32_t test_len = strlen(test_msg);
-
- PPP_DEBUG_INFO("Sending test AT command: \"%s\"", test_msg);
- ppp_error_t result = ppp_serial_write((const uint8_t *)test_msg, test_len);
-
- PPP_DEBUG_INFO("Test result: %s", result == PPP_ERR_OK ? "SUCCESS" : "FAILED");
- PPP_DEBUG_INFO("=== UART Test End ===");
-
- return result;
-}
/**
* @brief 强制发送缓冲区中的所有数据
#include <stdio.h>
#include "debug_print.h"
+/* 启用TCP测试详细日志 */
+#define ZHIHUI_TCP_LOG_ENABLE 1
+
/* 调试级别定义 */
#define ZHIHUI_TCP_LOG_LEVEL_NONE 0
#define ZHIHUI_TCP_LOG_LEVEL_ERROR 1
/* TCP测试配置 */
#define TCP_TEST_MAX_CONNECTIONS 50 // 最大连接数
-#define TCP_TEST_MIN_DATA_SIZE 1 // 最小数据包大小
+#define TCP_TEST_MIN_DATA_SIZE 1024 // 最小数据包大小
#define TCP_TEST_MAX_DATA_SIZE 4096 // 最大数据包大小
#define TCP_TEST_STATS_INTERVAL 5 // 统计报告间隔(秒)
#define TCP_TEST_CONNECT_TIMEOUT 10 // 连接超时时间(秒)
-#define TCP_TEST_RECV_TIMEOUT 1 // 接收超时时间(秒)
+#define TCP_TEST_RECV_TIMEOUT 5 // 接收超时时间(秒) - 从1秒增加到5秒以适应网络延迟
#define TCP_TEST_DEFAULT_HOST "110.42.224.129"
#define TCP_TEST_DEFAULT_PORT 8910
#define TCP_TEST_DEFAULT_TIME 30
#define TCP_TEST_DEFAULT_CONNECTIONS 10
+#define TCP_TEST_DEFAULT_RECV_TIMEOUT_MS 1000 // 默认接收超时1000ms
+
+/* 新的固定数据模式配置 */
+#define TCP_TEST_FIXED_DATA_SIZE 1024 // 固定数据长度,可通过宏配置
+#define TCP_DATA_PATTERN_CYCLE 256 // 数据模式循环:0x00 ~ 0xFF
/* TCP测试配置结构体 */
typedef struct {
uint32_t send_interval_ms; // 发送间隔(毫秒)
uint32_t data_min_size; // 最小数据包大小
uint32_t data_max_size; // 最大数据包大小
+ uint32_t recv_timeout_ms; // 接收超时时间(毫秒),默认1000ms
} tcp_test_config_t;
/* 单个连接统计信息 */
int socket_fd; // socket文件描述符
bool connected; // 连接状态
uint32_t connect_time_ms; // 连接耗时(毫秒)
+
+ // 发送统计
uint32_t packets_sent; // 发送包数
- uint32_t packets_received; // 接收包数
uint64_t bytes_sent; // 发送字节数
+ uint32_t send_errors; // 发送错误数
+ uint8_t current_send_pattern; // 当前发送数据模式值
+
+ // 接收统计
+ uint32_t packets_received; // 接收包数
uint64_t bytes_received; // 接收字节数
- uint32_t errors; // 错误数
- uint32_t data_errors; // 数据校验错误数
+ uint32_t recv_errors; // 接收错误数
+ uint32_t incomplete_packets; // 不完整包数
+ uint32_t incomplete_bytes; // 不完整字节数
+ uint32_t pattern_errors; // 数据模式错误数
+ uint8_t expected_recv_pattern; // 期望接收数据模式值
+
+ // 通用统计
+ uint32_t errors; // 总错误数
uint32_t last_activity_time; // 最后活动时间
- uint64_t throughput_bps; // 当前吞吐量(字节/秒)
- uint64_t max_throughput_bps; // 最大吞吐量(字节/秒)
- bool thread_running; // 线程运行状态
+ uint64_t send_throughput_bps; // 发送吞吐量(字节/秒)
+ uint64_t recv_throughput_bps; // 接收吞吐量(字节/秒)
+ uint64_t max_send_throughput_bps; // 最大发送吞吐量(字节/秒)
+ uint64_t max_recv_throughput_bps; // 最大接收吞吐量(字节/秒)
+
+ // 线程状态
+ bool send_thread_running; // 发送线程运行状态
+ bool recv_thread_running; // 接收线程运行状态
+ void *send_thread_handle; // 发送线程句柄
+ void *recv_thread_handle; // 接收线程句柄
} tcp_connection_stats_t;
/* 全局测试统计信息 */
uint32_t end_time; // 测试结束时间
uint16_t successful_connections; // 成功连接数
uint16_t failed_connections; // 失败连接数
+
+ // 发送统计
uint64_t total_packets_sent; // 总发送包数
- uint64_t total_packets_received; // 总接收包数
uint64_t total_bytes_sent; // 总发送字节数
+ uint32_t total_send_errors; // 总发送错误数
+ uint64_t max_send_throughput_bps; // 最大发送吞吐量(字节/秒)
+ uint64_t avg_send_throughput_bps; // 平均发送吞吐量(字节/秒)
+
+ // 接收统计
+ uint64_t total_packets_received; // 总接收包数
uint64_t total_bytes_received; // 总接收字节数
+ uint32_t total_recv_errors; // 总接收错误数
+ uint32_t total_incomplete_packets; // 总不完整包数
+ uint32_t total_incomplete_bytes; // 总不完整字节数
+ uint32_t total_pattern_errors; // 总数据模式错误数
+ uint64_t max_recv_throughput_bps; // 最大接收吞吐量(字节/秒)
+ uint64_t avg_recv_throughput_bps; // 平均接收吞吐量(字节/秒)
+
+ // 通用统计
uint32_t total_errors; // 总错误数
- uint32_t data_verification_errors; // 数据校验错误数
- uint64_t max_throughput_bps; // 最大吞吐量(字节/秒)
- uint64_t avg_throughput_bps; // 平均吞吐量(字节/秒)
bool test_running; // 测试运行状态
} tcp_global_stats_t;
static bool g_tcp_test_initialized = false;
/* 内部函数声明 */
-static errcode_t tcp_test_create_connection_thread(uint16_t conn_id);
-static void* tcp_test_connection_worker(void *arg);
-static errcode_t tcp_test_generate_data(uint16_t conn_id, uint32_t packet_id,
- uint8_t *buffer, uint32_t size);
-static uint32_t tcp_test_calculate_checksum(const uint8_t *data, uint32_t size);
-static bool tcp_test_verify_data(const uint8_t *sent_data, const uint8_t *recv_data, uint32_t size);
+static errcode_t tcp_test_create_connection_threads(uint16_t conn_id);
+static void* tcp_test_send_worker(void *arg);
+static void* tcp_test_recv_worker(void *arg);
+static errcode_t tcp_test_generate_fixed_pattern_data(uint8_t pattern_value, uint8_t *buffer, uint32_t size);
+static bool tcp_test_verify_fixed_pattern_data(const uint8_t *data, uint32_t size, uint8_t expected_pattern,
+ uint32_t *incomplete_bytes, uint32_t *pattern_errors);
static void tcp_test_stats_timer_callback(void *arg);
static void tcp_test_signal_handler(int signum);
-static errcode_t tcp_test_connect_socket(int *sock_fd, const char *host, uint16_t port);
+static errcode_t tcp_test_connect_socket(int *sock_fd, const char *host, uint16_t port, uint32_t recv_timeout_ms);
static int zhihui_tcp_debug_level = DEFAULT_ZHIHUI_TCP_LOG_LEVEL;
int zhihui_tcp_debug_get_level(void)
TCP_TEST_STATS_INTERVAL * 1000,
TCP_TEST_STATS_INTERVAL * 1000);
- // 创建连接线程
+ // 创建连接线程(发送和接收分离)
for (int i = 0; i < config->connection_count; i++) {
- errcode_t ret = tcp_test_create_connection_thread(i);
+ errcode_t ret = tcp_test_create_connection_threads(i);
if (ret != ERRCODE_SUCC) {
- ZHIHUI_TCP_LOG_ERROR("Failed to create connection thread %d", i);
+ ZHIHUI_TCP_LOG_ERROR("Failed to create connection threads %d", i);
tcp_test_stop();
return ret;
}
for (int i = 0; i < g_tcp_test_manager.config.connection_count; i++) {
tcp_connection_stats_t *conn = &g_tcp_test_manager.connections[i];
- if (conn->thread_running) {
+ if (conn->send_thread_running || conn->recv_thread_running) {
all_threads_stopped = false;
break;
}
}
/**
- * @brief 创建连接线程
+ * @brief 创建连接线程(发送和接收分离)
*/
-static errcode_t tcp_test_create_connection_thread(uint16_t conn_id)
+static errcode_t tcp_test_create_connection_threads(uint16_t conn_id)
{
- uint16_t *arg = malloc(sizeof(uint16_t));
- if (!arg) {
- return ERRCODE_FAIL;
- }
-
- *arg = conn_id;
-
- TCP_TASK_CREATE(tcp_test_connection_worker, arg, "tcp_test_conn", 8192);
-
- return ERRCODE_SUCC;
-}
-
-/**
- * @brief 连接工作线程
- */
-static void* tcp_test_connection_worker(void *arg)
-{
- uint16_t conn_id = *(uint16_t*)arg;
- free(arg);
-
tcp_connection_stats_t *conn = &g_tcp_test_manager.connections[conn_id];
tcp_test_config_t *config = &g_tcp_test_manager.config;
- conn->thread_running = true;
-
+ // 首先建立连接
uint32_t connect_start = tcp_test_get_time_ms();
-
- // 建立连接
errcode_t ret = tcp_test_connect_socket(&conn->socket_fd,
config->server_host,
- config->server_port);
+ config->server_port,
+ config->recv_timeout_ms);
if (ret != ERRCODE_SUCC) {
ZHIHUI_TCP_LOG_ERROR("[连接 %03d] 连接失败", conn_id);
TCP_MUTEX_LOCK(g_tcp_stats_mutex);
g_tcp_test_manager.global_stats.failed_connections++;
TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
- conn->thread_running = false;
- return NULL;
+ return ret;
}
conn->connected = true;
conn->connect_time_ms = tcp_test_get_time_ms() - connect_start;
+ // 初始化数据模式
+ conn->current_send_pattern = 0;
+ conn->expected_recv_pattern = 0;
+
TCP_MUTEX_LOCK(g_tcp_stats_mutex);
g_tcp_test_manager.global_stats.successful_connections++;
TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
- printf("[连接 %03d] 连接成功,耗时 %d ms\n", conn_id, conn->connect_time_ms);
+ ZHIHUI_TCP_LOG_INFO("[连接 %03d] 连接成功,耗时 %d ms", conn_id, conn->connect_time_ms);
- // 数据传输循环
- uint32_t packet_counter = 0;
- uint8_t *send_buffer = malloc(TCP_TEST_MAX_DATA_SIZE);
- uint8_t *recv_buffer = malloc(TCP_TEST_MAX_DATA_SIZE);
+ // 创建发送线程
+ uint16_t *send_arg = malloc(sizeof(uint16_t));
+ if (!send_arg) {
+ TCP_CLOSE(conn->socket_fd);
+ return ERRCODE_FAIL;
+ }
+ *send_arg = conn_id;
+
+ TCP_TASK_CREATE(tcp_test_send_worker, send_arg, "tcp_send", 2048);
- if (!send_buffer || !recv_buffer) {
- ZHIHUI_TCP_LOG_ERROR("[连接 %03d] 内存分配失败", conn_id);
- if (send_buffer) free(send_buffer);
- if (recv_buffer) free(recv_buffer);
- conn->errors++;
- goto thread_exit;
+ // 创建接收线程
+ uint16_t *recv_arg = malloc(sizeof(uint16_t));
+ if (!recv_arg) {
+ free(send_arg);
+ TCP_CLOSE(conn->socket_fd);
+ return ERRCODE_FAIL;
+ }
+ *recv_arg = conn_id;
+
+ TCP_TASK_CREATE(tcp_test_recv_worker, recv_arg, "tcp_recv", 2048);
+
+ return ERRCODE_SUCC;
+}
+
+/**
+ * @brief 发送工作线程 - 只负责发送固定模式数据
+ */
+static void* tcp_test_send_worker(void *arg)
+{
+ uint16_t conn_id = *(uint16_t*)arg;
+ free(arg);
+
+ tcp_connection_stats_t *conn = &g_tcp_test_manager.connections[conn_id];
+ tcp_test_config_t *config = &g_tcp_test_manager.config;
+
+ conn->send_thread_running = true;
+
+ // 分配发送缓冲区 - 使用动态分配避免栈溢出
+ uint8_t *send_buffer = malloc(TCP_TEST_FIXED_DATA_SIZE);
+ if (!send_buffer) {
+ ZHIHUI_TCP_LOG_ERROR("[发送 %03d] 内存分配失败", conn_id);
+ conn->send_thread_running = false;
+ return NULL;
}
uint32_t test_end_time = g_tcp_test_manager.global_stats.start_time +
(config->test_duration * 1000);
+ ZHIHUI_TCP_LOG_INFO("[发送 %03d] 开始发送数据,固定长度: %d 字节", conn_id, TCP_TEST_FIXED_DATA_SIZE);
+
+ uint32_t packet_counter = 0;
+ uint32_t send_interval_ms = config->send_interval_ms;
+ uint32_t last_send_time = 0;
+ uint8_t current_pattern = conn->current_send_pattern;
+
while (!g_tcp_test_manager.stop_flag &&
+ conn->connected &&
tcp_test_get_time_ms() < test_end_time) {
- // 生成随机大小的测试数据
- uint32_t data_size = config->data_min_size +
- (rand() % (config->data_max_size - config->data_min_size + 1));
-
- // 生成测试数据
- ret = tcp_test_generate_data(conn_id, packet_counter, send_buffer, data_size);
- if (ret != ERRCODE_SUCC) {
- conn->errors++;
- continue;
- }
-
- // 发送数据
- ZHIHUI_TCP_LOG_DEBUG("[连接 %03d] 准备发送 %d 字节数据", conn_id, data_size);
- ZHIHUI_TCP_LOG_DEBUG("[连接 %03d] Socket FD: %d, 连接状态: %s",
- conn_id, conn->socket_fd, conn->connected ? "已连接" : "未连接");
+ uint32_t current_time = tcp_test_get_time_ms();
- // 检查socket状态
- int socket_error = 0;
- socklen_t error_len = sizeof(socket_error);
- if (TCP_GETSOCKOPT(conn->socket_fd, SOL_SOCKET, SO_ERROR, &socket_error, &error_len) == 0) {
- if (socket_error != 0) {
- ZHIHUI_TCP_LOG_ERROR("[连接 %03d] Socket错误状态: %d (%s)",
- conn_id, socket_error, TCP_STRERROR(socket_error));
- } else {
- ZHIHUI_TCP_LOG_DEBUG("[连接 %03d] Socket状态正常", conn_id);
- }
- }
+ // 检查是否可以发送
+ bool can_send = (send_interval_ms == 0) ||
+ (current_time - last_send_time >= send_interval_ms);
- ssize_t bytes_sent = TCP_SEND(conn->socket_fd, send_buffer, data_size, 0);
- ZHIHUI_TCP_LOG_DEBUG("[连接 %03d] TCP_SEND返回: %ld (期望: %d)", conn_id, bytes_sent, data_size);
-
- if (bytes_sent != (ssize_t)data_size) {
- if (bytes_sent < 0) {
- int err = TCP_GET_ERRNO();
- ZHIHUI_TCP_LOG_ERROR("[连接 %03d] 发送失败: %s (errno: %d)",
- conn_id, TCP_STRERROR(err), err);
- ZHIHUI_TCP_LOG_ERROR("[连接 %03d] 发送失败详情: socket_fd=%d, data_size=%d, flags=0",
- conn_id, conn->socket_fd, data_size);
- conn->errors++;
- break;
- } else {
- ZHIHUI_TCP_LOG_WARN("[连接 %03d] 发送不完整 (%ld/%d 字节)",
- conn_id, bytes_sent, data_size);
- ZHIHUI_TCP_LOG_WARN("[连接 %03d] 部分发送可能是正常的,继续执行", conn_id);
+ if (can_send) {
+ // 生成固定模式数据
+ errcode_t ret = tcp_test_generate_fixed_pattern_data(current_pattern, send_buffer, TCP_TEST_FIXED_DATA_SIZE);
+ if (ret != ERRCODE_SUCC) {
+ TCP_MUTEX_LOCK(g_tcp_stats_mutex);
+ conn->send_errors++;
+ g_tcp_test_manager.global_stats.total_send_errors++;
+ TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
+ TCP_SLEEP_MS(1);
+ continue;
}
- } else {
- ZHIHUI_TCP_LOG_DEBUG("[连接 %03d] 发送成功: %ld 字节", conn_id, bytes_sent);
- }
-
- conn->packets_sent++;
- conn->bytes_sent += bytes_sent;
-
- // 接收回显数据
- ssize_t total_received = 0;
- uint32_t recv_start = tcp_test_get_time_ms();
-
- while (total_received < data_size &&
- (tcp_test_get_time_ms() - recv_start) < (TCP_TEST_RECV_TIMEOUT * 1000)) {
- ssize_t bytes_recv = TCP_RECV(conn->socket_fd,
- recv_buffer + total_received,
- data_size - total_received,
- 0);
+ // 发送数据
+ ssize_t bytes_sent = TCP_SEND(conn->socket_fd, send_buffer, TCP_TEST_FIXED_DATA_SIZE, 0);
- if (bytes_recv > 0) {
- total_received += bytes_recv;
- } else if (bytes_recv == 0) {
- ZHIHUI_TCP_LOG_WARN("[连接 %03d] 连接关闭", conn_id);
- goto thread_exit;
+ if (bytes_sent > 0) {
+ TCP_MUTEX_LOCK(g_tcp_stats_mutex);
+ conn->packets_sent++;
+ conn->bytes_sent += bytes_sent;
+ g_tcp_test_manager.global_stats.total_packets_sent++;
+ g_tcp_test_manager.global_stats.total_bytes_sent += bytes_sent;
+ TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
+
+ packet_counter++;
+ last_send_time = current_time;
+
+ ZHIHUI_TCP_LOG_DEBUG("[发送 %03d] 发送数据包 %d: 模式 0x%02X, %ld 字节",
+ conn_id, packet_counter, current_pattern, bytes_sent);
+
+ // 移动到下一个数据模式
+ current_pattern = (current_pattern + 1) % TCP_DATA_PATTERN_CYCLE;
+ conn->current_send_pattern = current_pattern;
+
} else {
int err = TCP_GET_ERRNO();
if (err != TCP_EAGAIN && err != TCP_EWOULDBLOCK) {
- ZHIHUI_TCP_LOG_ERROR("[连接 %03d] 接收失败: %s", conn_id, TCP_STRERROR(err));
- conn->errors++;
- goto thread_exit;
+ ZHIHUI_TCP_LOG_ERROR("[发送 %03d] 发送失败: %s", conn_id, TCP_STRERROR(err));
+ TCP_MUTEX_LOCK(g_tcp_stats_mutex);
+ conn->send_errors++;
+ g_tcp_test_manager.global_stats.total_send_errors++;
+ TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
+ break;
}
}
-
- TCP_SLEEP_MS(1); // 1ms延迟
}
- if (total_received == data_size) {
- conn->packets_received++;
- conn->bytes_received += total_received;
+ conn->last_activity_time = tcp_test_get_time_ms();
+
+ // 短暂延迟避免CPU占用过高
+ TCP_SLEEP_MS(send_interval_ms > 0 ? 1 : 0);
+ }
+
+ free(send_buffer);
+ conn->send_thread_running = false;
+
+ ZHIHUI_TCP_LOG_INFO("[发送 %03d] 发送线程结束,总发送: %d 包", conn_id, packet_counter);
+ return NULL;
+}
+
+/**
+ * @brief 接收工作线程 - 检测固定模式数据
+ */
+static void* tcp_test_recv_worker(void *arg)
+{
+ uint16_t conn_id = *(uint16_t*)arg;
+ free(arg);
+
+ tcp_connection_stats_t *conn = &g_tcp_test_manager.connections[conn_id];
+ tcp_test_config_t *config = &g_tcp_test_manager.config;
+
+ conn->recv_thread_running = true;
+
+ // 分配接收缓冲区
+ uint8_t *recv_buffer = malloc(TCP_TEST_FIXED_DATA_SIZE * 4); // 多缓冲一些数据
+ if (!recv_buffer) {
+ ZHIHUI_TCP_LOG_ERROR("[接收 %03d] 内存分配失败", conn_id);
+ conn->recv_errors++;
+ conn->recv_thread_running = false;
+ return NULL;
+ }
+
+ uint32_t test_end_time = g_tcp_test_manager.global_stats.start_time +
+ (config->test_duration * 1000);
+
+ ZHIHUI_TCP_LOG_INFO("[接收 %03d] 开始接收数据,固定长度: %d 字节", conn_id, TCP_TEST_FIXED_DATA_SIZE);
+ ZHIHUI_TCP_LOG_INFO("[接收 %03d] Socket FD: %d, 测试结束时间: %u", conn_id, conn->socket_fd, test_end_time);
+
+ uint32_t recv_buffer_offset = 0;
+ uint8_t expected_pattern = conn->expected_recv_pattern;
+ uint32_t total_incomplete_bytes = 0;
+ uint32_t total_pattern_errors = 0;
+
+ ZHIHUI_TCP_LOG_INFO("[接收 %03d] 进入接收循环", conn_id);
+
+ while (!g_tcp_test_manager.stop_flag &&
+ conn->connected &&
+ tcp_test_get_time_ms() < test_end_time) {
+
+ // 接收数据
+ ssize_t bytes_recv = TCP_RECV(conn->socket_fd,
+ recv_buffer + recv_buffer_offset,
+ (TCP_TEST_FIXED_DATA_SIZE * 4) - recv_buffer_offset,
+ 0);
+
+ if (bytes_recv > 0) {
+ recv_buffer_offset += bytes_recv;
+
+ ZHIHUI_TCP_LOG_INFO("[接收 %03d] 接收到 %ld 字节,缓冲区总计: %d 字节",
+ conn_id, bytes_recv, recv_buffer_offset);
- // 验证数据完整性
- if (!tcp_test_verify_data(send_buffer, recv_buffer, data_size)) {
- conn->data_errors++;
+ // 处理完整的固定长度数据包
+ while (recv_buffer_offset >= TCP_TEST_FIXED_DATA_SIZE) {
+ uint32_t incomplete_bytes = 0;
+ uint32_t pattern_errors = 0;
+
+ // 验证固定模式数据
+ bool data_valid = tcp_test_verify_fixed_pattern_data(
+ recv_buffer, TCP_TEST_FIXED_DATA_SIZE, expected_pattern,
+ &incomplete_bytes, &pattern_errors);
+
+ // 更新接收统计
TCP_MUTEX_LOCK(g_tcp_stats_mutex);
- g_tcp_test_manager.global_stats.data_verification_errors++;
+ conn->packets_received++;
+ conn->bytes_received += TCP_TEST_FIXED_DATA_SIZE;
+ g_tcp_test_manager.global_stats.total_packets_received++;
+ g_tcp_test_manager.global_stats.total_bytes_received += TCP_TEST_FIXED_DATA_SIZE;
+
+ if (!data_valid) {
+ conn->pattern_errors += pattern_errors;
+ g_tcp_test_manager.global_stats.total_pattern_errors += pattern_errors;
+ total_pattern_errors += pattern_errors;
+ }
+
+ if (incomplete_bytes > 0) {
+ conn->incomplete_bytes += incomplete_bytes;
+ g_tcp_test_manager.global_stats.total_incomplete_bytes += incomplete_bytes;
+ total_incomplete_bytes += incomplete_bytes;
+ }
+
TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
+
+ ZHIHUI_TCP_LOG_INFO("[接收 %03d] 包验证: 期望模式 0x%02X, %s, 错误: %d",
+ conn_id, expected_pattern,
+ data_valid ? "正确" : "错误", pattern_errors);
+
+ // 移动到下一个期望的数据模式
+ expected_pattern = (expected_pattern + 1) % TCP_DATA_PATTERN_CYCLE;
+ conn->expected_recv_pattern = expected_pattern;
+
+ // 移除已处理的数据
+ memmove(recv_buffer, recv_buffer + TCP_TEST_FIXED_DATA_SIZE,
+ recv_buffer_offset - TCP_TEST_FIXED_DATA_SIZE);
+ recv_buffer_offset -= TCP_TEST_FIXED_DATA_SIZE;
}
+
+ } else if (bytes_recv == 0) {
+ ZHIHUI_TCP_LOG_WARN("[接收 %03d] 连接关闭", conn_id);
+ break;
} else {
- ZHIHUI_TCP_LOG_WARN("[连接 %03d] 接收数据不完整: %ld/%d 字节",
- conn_id, total_received, data_size);
- conn->errors++;
- }
-
- // 更新全局统计
- TCP_MUTEX_LOCK(g_tcp_stats_mutex);
- g_tcp_test_manager.global_stats.total_packets_sent++;
- g_tcp_test_manager.global_stats.total_bytes_sent += bytes_sent;
- if (total_received == data_size) {
- g_tcp_test_manager.global_stats.total_packets_received++;
- g_tcp_test_manager.global_stats.total_bytes_received += total_received;
- } else {
- g_tcp_test_manager.global_stats.total_errors++;
+ int err = TCP_GET_ERRNO();
+ if (err == TCP_EAGAIN || err == TCP_EWOULDBLOCK) {
+ // 非阻塞模式下的正常超时
+ ZHIHUI_TCP_LOG_INFO("[接收 %03d] 接收超时 (EAGAIN/EWOULDBLOCK)", conn_id);
+ } else if (err == TCP_ETIMEDOUT) {
+ // Socket 超时
+ ZHIHUI_TCP_LOG_INFO("[接收 %03d] Socket 超时 (ETIMEDOUT)", conn_id);
+ } else {
+ ZHIHUI_TCP_LOG_ERROR("[接收 %03d] 接收失败: %s", conn_id, TCP_STRERROR(err));
+ TCP_MUTEX_LOCK(g_tcp_stats_mutex);
+ conn->recv_errors++;
+ g_tcp_test_manager.global_stats.total_recv_errors++;
+ TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
+ break;
+ }
}
- TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
conn->last_activity_time = tcp_test_get_time_ms();
- packet_counter++;
- // 控制发送频率
- if (config->send_interval_ms > 0) {
- TCP_SLEEP_MS(config->send_interval_ms);
- } else {
- TCP_SLEEP_MS((rand() % 10 + 1)); // 1-10ms随机延迟
- }
+ // 短暂延迟
+ TCP_SLEEP_MS(1);
}
-thread_exit:
- // 关闭连接
- if (conn->socket_fd >= 0) {
- TCP_CLOSE(conn->socket_fd);
- conn->socket_fd = -1;
+ // 处理剩余不完整数据
+ if (recv_buffer_offset > 0) {
+ TCP_MUTEX_LOCK(g_tcp_stats_mutex);
+ conn->incomplete_packets++;
+ conn->incomplete_bytes += recv_buffer_offset;
+ g_tcp_test_manager.global_stats.total_incomplete_packets++;
+ g_tcp_test_manager.global_stats.total_incomplete_bytes += recv_buffer_offset;
+ TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
+
+ ZHIHUI_TCP_LOG_WARN("[接收 %03d] 剩余不完整数据: %d 字节", conn_id, recv_buffer_offset);
}
- conn->connected = false;
- conn->thread_running = false;
-
- if (send_buffer) free(send_buffer);
- if (recv_buffer) free(recv_buffer);
+ free(recv_buffer);
+ conn->recv_thread_running = false;
+ ZHIHUI_TCP_LOG_INFO("[接收 %03d] 接收线程结束,总模式错误: %d, 总不完整字节: %d",
+ conn_id, total_pattern_errors, total_incomplete_bytes);
return NULL;
}
/**
* @brief 建立Socket连接
*/
-static errcode_t tcp_test_connect_socket(int *sock_fd, const char *host, uint16_t port)
+static errcode_t tcp_test_connect_socket(int *sock_fd, const char *host, uint16_t port, uint32_t recv_timeout_ms)
{
int fd = TCP_SOCKET(TCP_AF_INET, TCP_SOCK_STREAM, 0);
if (fd < 0) {
}
#ifndef USE_LWIP_SOCKET
- // 设置连接超时 (仅在POSIX环境下)
- struct timeval timeout;
- timeout.tv_sec = TCP_TEST_CONNECT_TIMEOUT;
- timeout.tv_usec = 0;
+ // 设置超时 (仅在POSIX环境下)
+ struct timeval connect_timeout;
+ connect_timeout.tv_sec = TCP_TEST_CONNECT_TIMEOUT;
+ connect_timeout.tv_usec = 0;
+
+ struct timeval recv_timeout;
+ recv_timeout.tv_sec = recv_timeout_ms / 1000;
+ recv_timeout.tv_usec = (recv_timeout_ms % 1000) * 1000;
- if (TCP_SETSOCKOPT(fd, TCP_SOL_SOCKET, TCP_SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0 ||
- TCP_SETSOCKOPT(fd, TCP_SOL_SOCKET, TCP_SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) {
- ZHIHUI_TCP_LOG_WARN("Failed to set socket timeout");
+ if (TCP_SETSOCKOPT(fd, TCP_SOL_SOCKET, TCP_SO_RCVTIMEO, &recv_timeout, sizeof(recv_timeout)) < 0) {
+ ZHIHUI_TCP_LOG_WARN("Failed to set socket receive timeout to %ums", recv_timeout_ms);
+ } else {
+ ZHIHUI_TCP_LOG_DEBUG("Socket receive timeout set to %ums", recv_timeout_ms);
+ }
+
+ if (TCP_SETSOCKOPT(fd, TCP_SOL_SOCKET, TCP_SO_SNDTIMEO, &connect_timeout, sizeof(connect_timeout)) < 0) {
+ ZHIHUI_TCP_LOG_WARN("Failed to set socket send timeout");
}
#else
// 在lwIP环境下设置超时 - 使用正确的数据类型和检查
#ifdef LWIP_SO_RCVTIMEO
- struct timeval timeout;
- timeout.tv_sec = TCP_TEST_CONNECT_TIMEOUT;
- timeout.tv_usec = 0;
+ struct timeval connect_timeout;
+ connect_timeout.tv_sec = TCP_TEST_CONNECT_TIMEOUT;
+ connect_timeout.tv_usec = 0;
+
+ struct timeval recv_timeout;
+ recv_timeout.tv_sec = recv_timeout_ms / 1000;
+ recv_timeout.tv_usec = (recv_timeout_ms % 1000) * 1000;
- if (TCP_SETSOCKOPT(fd, TCP_SOL_SOCKET, TCP_SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
- ZHIHUI_TCP_LOG_DEBUG("lwIP SO_RCVTIMEO not supported or failed");
+ if (TCP_SETSOCKOPT(fd, TCP_SOL_SOCKET, TCP_SO_RCVTIMEO, &recv_timeout, sizeof(recv_timeout)) < 0) {
+ ZHIHUI_TCP_LOG_DEBUG("lwIP SO_RCVTIMEO not supported or failed for %ums", recv_timeout_ms);
+ } else {
+ ZHIHUI_TCP_LOG_DEBUG("lwIP socket receive timeout set to %ums", recv_timeout_ms);
}
- if (TCP_SETSOCKOPT(fd, TCP_SOL_SOCKET, TCP_SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) {
+
+ if (TCP_SETSOCKOPT(fd, TCP_SOL_SOCKET, TCP_SO_SNDTIMEO, &connect_timeout, sizeof(connect_timeout)) < 0) {
ZHIHUI_TCP_LOG_DEBUG("lwIP SO_SNDTIMEO not supported or failed");
}
#else
// lwIP可能不支持超时选项,使用非阻塞模式代替
- ZHIHUI_TCP_LOG_INFO("lwIP socket timeout not supported, using default behavior");
+ ZHIHUI_TCP_LOG_INFO("lwIP socket timeout not supported, using default behavior (recv_timeout=%ums requested)", recv_timeout_ms);
#endif
#endif
}
/**
- * @brief 生成测试数据
+ * @brief 生成固定模式数据
*/
-static errcode_t tcp_test_generate_data(uint16_t conn_id, uint32_t packet_id,
- uint8_t *buffer, uint32_t size)
+static errcode_t tcp_test_generate_fixed_pattern_data(uint8_t pattern_value, uint8_t *buffer, uint32_t size)
{
- if (!buffer || size < sizeof(tcp_test_packet_header_t)) {
+ if (!buffer || size == 0) {
return ERRCODE_INVALID_PARAM;
}
- tcp_test_packet_header_t *header = (tcp_test_packet_header_t*)buffer;
- header->conn_id = TCP_HTONS(conn_id);
- header->packet_id = TCP_HTONL(packet_id);
- header->data_size = TCP_HTONS(size);
- header->timestamp = TCP_HTONL(tcp_test_get_time_ms());
-
- // 填充随机数据
- for (uint32_t i = sizeof(tcp_test_packet_header_t); i < size - sizeof(uint32_t); i++) {
- buffer[i] = rand() & 0xFF;
- }
-
- // 计算校验和
- header->checksum = TCP_HTONL(tcp_test_calculate_checksum(buffer, size - sizeof(uint32_t)));
+ // 填充固定模式数据,整个buffer都用同一个值
+ memset(buffer, pattern_value, size);
return ERRCODE_SUCC;
}
}
/**
- * @brief 验证数据完整性
+ * @brief 验证固定模式数据
*/
-static bool tcp_test_verify_data(const uint8_t *sent_data, const uint8_t *recv_data, uint32_t size)
+static bool tcp_test_verify_fixed_pattern_data(const uint8_t *data, uint32_t size, uint8_t expected_pattern,
+ uint32_t *incomplete_bytes, uint32_t *pattern_errors)
{
- return memcmp(sent_data, recv_data, size) == 0;
+ if (!data || size == 0 || !incomplete_bytes || !pattern_errors) {
+ return false;
+ }
+
+ *incomplete_bytes = 0;
+ *pattern_errors = 0;
+
+ for (uint32_t i = 0; i < size; i++) {
+ if (data[i] != expected_pattern) {
+ (*pattern_errors)++;
+ }
+ }
+
+ // 如果所有数据都正确,返回true
+ return (*pattern_errors == 0);
}
/**
/* 在lwIP环境中尝试使用真实的时间函数 */
#ifdef OSAL_TIME_AVAILABLE
/* 如果OSAL时间函数可用,使用它 */
- return osal_get_time_ms();
+ return osal_get_jiffies();
#else
/* 否则使用简化的时间模拟 */
static uint32_t start_time = 0;
printf("\n错误统计:\n");
printf(" 传输错误: %d\n", g_tcp_test_manager.global_stats.total_errors);
- printf(" æ\95°æ\8d®æ ¡éª\8cé\94\99误: %d\n", g_tcp_test_manager.global_stats.data_verification_errors);
+ printf(" æ\95°æ\8d®æ¨¡å¼\8fé\94\99误: %d\n", g_tcp_test_manager.global_stats.total_pattern_errors);
if (g_tcp_test_manager.global_stats.total_packets_sent > 0) {
printf(" 错误率: %.3f%%\n",
printf(" -c, --connections <数量> 并发连接数 (默认: %d, 最大: %d)\n",
TCP_TEST_DEFAULT_CONNECTIONS, TCP_TEST_MAX_CONNECTIONS);
printf(" -v, --verbose 详细输出模式\n");
- printf(" -i, --interval <毫秒> 发送间隔(毫秒) (默认: 自动)\n");
+ printf(" -i, --interval <毫秒> 发送间隔(毫秒) (默认: 20)\n");
printf(" --min-size <字节> 最小数据包大小 (默认: %d)\n", TCP_TEST_MIN_DATA_SIZE);
printf(" --max-size <字节> 最大数据包大小 (默认: %d)\n", TCP_TEST_MAX_DATA_SIZE);
printf(" -h, --help 显示此帮助信息\n\n");
config->test_duration = TCP_TEST_DEFAULT_TIME;
config->connection_count = TCP_TEST_DEFAULT_CONNECTIONS;
config->verbose = false;
- config->send_interval_ms = 0; // 自动
+ config->send_interval_ms = 20; // 默认20ms间隔
config->data_min_size = TCP_TEST_MIN_DATA_SIZE;
config->data_max_size = TCP_TEST_MAX_DATA_SIZE;
+ config->recv_timeout_ms = TCP_TEST_DEFAULT_RECV_TIMEOUT_MS; // 默认接收超时1000ms
// 长选项定义
static struct option long_options[] = {
printf(" 并发连接: %d\n", config->connection_count);
printf(" 数据包大小: %d-%d 字节\n", config->data_min_size, config->data_max_size);
printf(" 详细输出: %s\n", config->verbose ? "是" : "否");
-
- if (config->send_interval_ms > 0) {
- printf(" 发送间隔: %d 毫秒\n", config->send_interval_ms);
- } else {
- printf(" 发送间隔: 自动(1-10毫秒随机)\n");
- }
+ printf(" 发送间隔: %d 毫秒/包\n", config->send_interval_ms);
+ printf(" 接收超时: %d 毫秒\n", config->recv_timeout_ms);
printf("\n");
}
factory_set_recoder_streamType();
}
+#ifdef CUSTOM_UTILS
+ if(!custom_get_factory_test_flag())
+#endif
+ uapi_ln_http_server_init();
+
+
+#ifdef SUPPORT_PPP_SERVICE
+ ppp_env_init();
+#endif
+
#endif
#ifdef SUPPORT_CYWEE_SERVICE
do_cywee_service_check_msg(CYWEE_SERVICE_CMD_TIME_SYNC,NULL);
#endif
#else
-#ifdef BOARD_LEINIAO
- extern int ppp_env_init(void);
- if(!custom_get_factory_test_flag())
- ppp_env_init();
-#endif
+// #ifdef SUPPORT_PPP_SERVICE
+// extern errcode_t ppp_start_dial(void);
+ // if(!custom_get_factory_test_flag())
+ // ppp_start_dial();
+// #endif
#endif