From 64b60f41d481036f997b00abe42e473ebf0acdde Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E5=AD=99=E6=98=A5=E9=98=B3?= Date: Wed, 17 Sep 2025 19:39:27 +0800 Subject: [PATCH] =?utf8?q?ppp=E6=9C=80=E6=96=B0=E4=BB=A3=E7=A0=81=EF=BC=8C?= =?utf8?q?=E4=BC=98=E5=8C=96=E5=BC=80=E5=85=B3=E6=9C=BA=E6=B5=81=E7=A8=8B?= =?utf8?q?=EF=BC=8C=E6=AD=A3=E7=A1=AE=E9=85=8D=E7=BD=AEio=EF=BC=8C?= =?utf8?q?=E6=B7=BB=E5=8A=A0n9=E4=B8=ADai=E6=9C=8D=E5=8A=A1=E4=BB=A3?= =?utf8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../config/target_config/brandy/config.py | 13 +- code/sdk/drivers/drivers/driver/uart/uart.c | 44 +- code/sdk/zhihui/ai/src/http_getfile.c | 2 +- code/sdk/zhihui/ai_old/zhihui_ai_server.cpp | 4 +- code/sdk/zhihui/ai_old/zhihui_ws.cpp | 4 +- code/sdk/zhihui/ppp/CMakeLists.txt | 1 + code/sdk/zhihui/ppp/doc/at_cmd_list_annotated | 422 ++++++++++++++++ .../ppp/doc/cesq_implementation_summary.md | 1 + .../ppp/doc/signal_quality_assessment.md | 1 + .../zhihui/ppp/doc/stub_functions_readme.md | 1 + code/sdk/zhihui/ppp/example/api_shell.c | 2 +- code/sdk/zhihui/ppp/example/ppp_at_cmd.c | 22 +- code/sdk/zhihui/ppp/example/ppp_example.c | 4 +- .../zhihui/ppp/example/ppp_power_example.c | 192 -------- code/sdk/zhihui/ppp/include/ppp_api.h | 6 + code/sdk/zhihui/ppp/include/ppp_at_handler.h | 22 + code/sdk/zhihui/ppp/include/ppp_config.h | 6 +- code/sdk/zhihui/ppp/src/ppp_api.c | 456 ++++++++++++++---- code/sdk/zhihui/ppp/src/ppp_at_handler.c | 404 ++++++++++++---- code/sdk/zhihui/ppp/src/ppp_lwip.c | 41 +- code/sdk/zhihui/ppp/src/ppp_power_ctl.c | 67 ++- code/sdk/zhihui/ppp/src/ppp_serial.c | 3 + code/sdk/zhihui/ppp/src/ppp_stub_functions.c | 90 ++++ code/sdk/zhihui/utils/custom_utils.c | 5 + 24 files changed, 1359 insertions(+), 454 deletions(-) create mode 100644 code/sdk/zhihui/ppp/doc/at_cmd_list_annotated create mode 100644 code/sdk/zhihui/ppp/doc/cesq_implementation_summary.md create mode 100644 code/sdk/zhihui/ppp/doc/signal_quality_assessment.md create mode 100644 code/sdk/zhihui/ppp/doc/stub_functions_readme.md delete mode 100644 code/sdk/zhihui/ppp/example/ppp_power_example.c create mode 100644 code/sdk/zhihui/ppp/src/ppp_stub_functions.c diff --git a/code/sdk/build/config/target_config/brandy/config.py b/code/sdk/build/config/target_config/brandy/config.py index 00b37c96c..ad9d7e70a 100644 --- a/code/sdk/build/config/target_config/brandy/config.py +++ b/code/sdk/build/config/target_config/brandy/config.py @@ -1283,10 +1283,17 @@ target = { # "-:lwip", "thunderbird_toys",#雷鸟 "leiniaoMediaService", - # "cat1Service", - # "cat1Test", + #cat1 相关配置 "ppp", - "audio_manager", + #websocket 相关配置 + "zhihui_websocket", + #ai 相关配置 + "aiMediaService", + "aiService", + #ai_old相关配置 + "zhihui_ai_old", + #音频相关配置 + "audio_manager", # "CustomUIcomponentTool", "nativeabilityfwk", "custom_utils", diff --git a/code/sdk/drivers/drivers/driver/uart/uart.c b/code/sdk/drivers/drivers/driver/uart/uart.c index cf2c88ab8..214942b1d 100644 --- a/code/sdk/drivers/drivers/driver/uart/uart.c +++ b/code/sdk/drivers/drivers/driver/uart/uart.c @@ -686,6 +686,11 @@ int32_t uapi_uart_read_by_dma(uart_bus_t bus, const void *buffer, uint32_t lengt #endif /* CONFIG_UART_SUPPORT_TX */ #if defined(CONFIG_UART_SUPPORT_RX) +/* + * timeout的作用:如果在超时时间内一直没有数据到达,则退出; + * 如果有数据到达,则应持续读取,直到没有数据可读(即RX FIFO空), + * 此时才正常返回,不能因为超时而中断正在进行的数据读取。 + */ int32_t uapi_uart_read(uart_bus_t bus, const uint8_t *buffer, uint32_t length, uint32_t timeout) { #ifdef SUPPORT_GNSS @@ -709,11 +714,10 @@ int32_t uapi_uart_read(uart_bus_t bus, const uint8_t *buffer, uint32_t length, u return -1; } - /* Poll until we read the requested length or timeout expires. - If timeout == 0, behave non-blocking and return immediately if no data. */ - uint32_t time_remaining = timeout; - for (;;) { - /* Try to read one byte if available */ + uint32_t time_waited = 0; + bool got_data = false; + + while (len > 0) { uint32_t irq_sts = uart_porting_lock(bus); hal_funcs->ctrl(bus, UART_CTRL_CHECK_RX_FIFO_EMPTY, (uintptr_t)&rx_fifo_empty); if (!rx_fifo_empty) { @@ -721,27 +725,31 @@ int32_t uapi_uart_read(uart_bus_t bus, const uint8_t *buffer, uint32_t length, u data_buffer++; len--; read_count++; + got_data = true; + time_waited = 0; // reset wait time after receiving data } uart_porting_unlock(bus, irq_sts); if (len == 0) { - break; /* finished reading requested bytes */ + break; // 已读满length字节 } if (rx_fifo_empty) { - /* No data available now */ - if (timeout == 0) { - break; /* non-blocking: return whatever we got */ - } - if (time_remaining == 0) { - break; /* timed out */ - } - /* Sleep briefly and try again */ - osal_msleep(1); - if (time_remaining != 0xFFFFFFFF) { - if (time_remaining > 0) { - time_remaining--; + if (!got_data) { + // 尚未收到任何数据,等待timeout + if (timeout == 0) { + break; // 非阻塞模式 + } + if (time_waited >= timeout) { + break; // 超时未收到任何数据 } + osal_msleep(1); + if (timeout != 0xFFFFFFFF) { + time_waited++; + } + } else { + // 已经收到过数据,只要RX FIFO空就返回 + break; } } } diff --git a/code/sdk/zhihui/ai/src/http_getfile.c b/code/sdk/zhihui/ai/src/http_getfile.c index 00a77b031..f44a10f65 100644 --- a/code/sdk/zhihui/ai/src/http_getfile.c +++ b/code/sdk/zhihui/ai/src/http_getfile.c @@ -5,7 +5,7 @@ #include "custom_utils.h" #include "custom_runtime.h" -#include "bleANCS.h" +// #include "bleANCS.h" #include "custom_utils.h" #include "cmsis_os2.h" #include "wearable_log.h" diff --git a/code/sdk/zhihui/ai_old/zhihui_ai_server.cpp b/code/sdk/zhihui/ai_old/zhihui_ai_server.cpp index ddc8d9b5d..8b4e7c00f 100644 --- a/code/sdk/zhihui/ai_old/zhihui_ai_server.cpp +++ b/code/sdk/zhihui/ai_old/zhihui_ai_server.cpp @@ -22,7 +22,7 @@ // #include "bletest.h" // Commented out due to missing header #include "custom_utils.h" #include "custom_runtime.h" -#include "bleANCS.h" +// #include "bleANCS.h" #include "cat1_tcpServer.h" #include "custom_utils.h" #include "broadcast_feature.h" @@ -32,7 +32,7 @@ #include "audio_capture_wrapper.h" // #include // Commented out due to missing header -#include +// #include // #include "cat1_ws.h" // Commented out due to missing header #include "dev_authentication.h" #include "bk_websocket.h" diff --git a/code/sdk/zhihui/ai_old/zhihui_ws.cpp b/code/sdk/zhihui/ai_old/zhihui_ws.cpp index dd6af8ec5..d741fc1cb 100644 --- a/code/sdk/zhihui/ai_old/zhihui_ws.cpp +++ b/code/sdk/zhihui/ai_old/zhihui_ws.cpp @@ -48,7 +48,7 @@ // #include "bletest.h" // Commented out due to missing header #include "custom_utils.h" #include "custom_runtime.h" -#include "bleANCS.h" +// #include "bleANCS.h" #include "custom_utils.h" #include "broadcast_feature.h" #include "cmsis_os2.h" @@ -57,7 +57,7 @@ #include "audio_capture_wrapper.h" // #include // Commented out due to missing header -#include +// #include #include "zhihui_ws.h" #include "dev_authentication.h" // #include "tcp_simple_manager.h" // Commented out due to missing header diff --git a/code/sdk/zhihui/ppp/CMakeLists.txt b/code/sdk/zhihui/ppp/CMakeLists.txt index ec64279f8..41539d69a 100644 --- a/code/sdk/zhihui/ppp/CMakeLists.txt +++ b/code/sdk/zhihui/ppp/CMakeLists.txt @@ -21,6 +21,7 @@ set(SOURCES src/ppp_debug.c src/ppp_power_ctl.c src/ppp_cat1_api.c + src/ppp_stub_functions.c ${PPP_AT_CMD_SOURCE} ) diff --git a/code/sdk/zhihui/ppp/doc/at_cmd_list_annotated b/code/sdk/zhihui/ppp/doc/at_cmd_list_annotated new file mode 100644 index 000000000..c9927fc51 --- /dev/null +++ b/code/sdk/zhihui/ppp/doc/at_cmd_list_annotated @@ -0,0 +1,422 @@ +# Neoway N706A AT命令列表 (带备注) +# 基于 Neoway_N706A_AT命令手册_V1.0.md + +» AT+CLAC # 列出所有可用的AT命令 +« AT+CLAC + +AT+CFUN # 设置模组功能 (0=最小功能,1=全功能,4=飞行模式等) + +AT+CSQ # 获取信号强度 (返回信号强度和误码率) + +AT+COPS # 运营商选择 (查询/设置网络运营商) + +AT+CGATT # GPRS附着/分离 (1=附着,0=分离) + +AT+CTZR # 时区报告设置 + +AT+CCLK # 时钟设置/查询 + +AT+CEREG # EPS网络注册状态 + +AT+CPLS # 选择首选语言 + +AT+CPOL # 首选运营商列表 + +AT+COPN # 读取运营商名称 + +AT+NPSMR # 【未匹配到】 + +AT+NPSMSET # 【未匹配到】 + +AT+NEARFCN # 【未匹配到】 + +AT+CPSMS # 省电模式设置 + +AT+NBAND # 【未匹配到】 + +AT+CNEC # 【未匹配到】 + +AT+CTZU # 自动时区更新 + +AT+NDRX # 【未匹配到】 + +AT+CSCON # 信令连接状态 + +AT+NCSEARFCN # 【未匹配到】 + +AT+NUESTATS # 【未匹配到】 + +AT+NPOWD # 【未匹配到】 + +AT+CREG # 网络注册状态 (查询网络注册状态) + +AT+CGREG # GPRS网络注册状态 + +AT+NSQ # 【未匹配到】 + +AT+NNMPSD # 【未匹配到】 + +AT+NGSBLACKCELL # 【未匹配到】 + +AT+NCSBLACKCELL # 【未匹配到】 + +AT+NBACKOFF # 【未匹配到】 + +AT+NROAMING # 【未匹配到】 + +AT+NRESELCFG # 【未匹配到】 + +AT+NSIMAC # 【未匹配到】 + +AT+CGTFT # 流量模板 + +AT+CGPADDR # 显示PDP地址 + +AT+CGDCONT # 定义PDP上下文 (设置APN等参数) + +AT+CGACT # PDP上下文激活/去激活 + +AT+CGCMOD # PDP上下文修改 + +AT+CGDSCONT # 定义辅助PDP上下文 + +AT+CGTFTRDP # 读取流量模板 + +AT+CGEQOSRDP # 读取EPS QoS参数 + +AT+CGAUTH # 定义PDP上下文认证参数 + +AT+CGEQOS # 定义EPS QoS参数 + +AT+CEER # 扩展错误报告 + +AT+CGCONTRDP # 读取动态PDP上下文参数 + +AT+NCONFIG # 【未匹配到】 + +AT+CIMI # 请求国际移动用户识别码(IMSI) + +AT+CGLA # 通用逻辑通道访问 + +AT+CRSM # 受限SIM访问 + +AT+CSIM # 通用SIM访问 + +AT+CCHC # 关闭逻辑通道 + +AT+CCHO # 打开逻辑通道 + +AT+USIMHOTPLUG # 【未匹配到】 + +AT+NUICC # 【未匹配到】 + +AT+ICCID # 读取ICCID (SIM卡序列号) + +AT+PHONENUM # 【未匹配到】 + +AT+NSIMSRS # 【未匹配到】 + +AT+CLEARFPLMN # 【未匹配到】 + +AT+USIMRETRYTIMES # 【未匹配到】 + +AT+CPIN # 输入PIN码 + +AT+CLCK # 设备锁定 + +AT+CPWD # 更改密码 + +AT+NPIN # 【未匹配到】 + +AT+SETHWLOCK # 【未匹配到】 + +AT+CARDLOCK # 【未匹配到】 + +AT+SIMLOCK # 【未匹配到】 + +AT+CPINR # PIN剩余尝试次数 + +AT+CMEE # 移动设备错误报告 + +AT+CGMI # 请求制造商标识 + +AT+CGSN # 请求产品序列号标识 (IMEI) + +AT+CLAC # 列出所有可用的AT命令 (重复) + +AT+RESET # 【未匹配到】 + +AT+NLOGLEVEL # 【未匹配到】 + +AT+NATSPEED # 【未匹配到】 + +AT+NFWUPD # 【未匹配到】 + +AT+NDSDELAY # 【未匹配到】 + +AT+NCRASHINFO # 【未匹配到】 + +AT+NTSETID # 【未匹配到】 + +AT+NTPERMID # 【未匹配到】 + +AT+NCHIPTYPE # 【未匹配到】 + +AT+NQSTATE # 【未匹配到】 + +AT+USIMSEL # 【未匹配到】 + +AT+NVETOSUPERDS # 【未匹配到】 + +AT+NBANKD # 【未匹配到】 + +AT+NVER # 【未匹配到】 + +AT+MODEMTEMP # 【未匹配到】 + +AT+NRCUPD # 【未匹配到】 + +AT+NLOGMODFT # 【未匹配到】 + +AT+NRDCTRL # 【未匹配到】 + +AT+NRDSET # 【未匹配到】 + +AT+NRDEXEC # 【未匹配到】 + +AT+NGOLD # 【未匹配到】 + +AT+NDISDUP # 【未匹配到】 + +AT+NPING # 【未匹配到】 + +AT+NDNS # 【未匹配到】 + +AT+NSOCR # 创建socket + +AT+NSOST # 发送数据到socket + +AT+NSOCO # 连接socket + +AT+NSOSD # 发送数据并关闭socket + +AT+NQSOS # 查询socket状态 + +AT+NSORF # 从socket接收数据 + +AT+NSOCL # 关闭socket + +AT+NSOSTATUS # 【未匹配到】 + +AT+NCIDSTATUS # 【未匹配到】 + +AT+NDATATRAN # 【未匹配到】 + +AT+NIPINFO # 【未匹配到】 + +AT+NKEEPALIVE # 【未匹配到】 + +AT+NISEND # 【未匹配到】 + +AT+NDATARATE # 【未匹配到】 + +AT+NRDTEST # 【未匹配到】 + +AT+NWIFISCAN # 【未匹配到】 + +AT+NWIFISCANSTOP # 【未匹配到】 + +AT+NTXPOWER # 【未匹配到】 + +AT+DEMO # 【未匹配到】 + +AT+IVSN # 【未匹配到】 + +AT+GMR # 请求修订版本标识 (固件版本) + +AT+FTCAL # 【未匹配到】 + +AT+FTRF # 【未匹配到】 + +AT+IMEI # 【未匹配到】 + +AT+IFC # 设置本地数据流控制 + +AT+ICF # 设置字符格式 + +AT+IPR # 设置波特率 + +AT+NWIDCFG # 【未匹配到】 + +AT+CERTADD # 【未匹配到】 + +AT+CERTCHECK # 【未匹配到】 + +AT+CERTDEL # 【未匹配到】 + +AT+IPINFO # 【未匹配到】 + +AT+IPSTATUS # 【未匹配到】 + +AT+PDPKEEPALIVE # 【未匹配到】 + +AT+PDPSTATUS # 【未匹配到】 + +AT+RECVMODE # 【未匹配到】 + +AT+TCPACK # TCP确认 + +AT+TCPCLOSE # 关闭TCP连接 + +AT+TCPKEEPALIVE # TCP保活设置 + +AT+TCPREAD # 读取TCP数据 + +AT+TCPSEND # 发送TCP数据 + +AT+TCPSETUP # 建立TCP连接 + +AT+TCPTRANS # TCP透传模式 + +AT+TRANSCLOSE # 关闭透传连接 + +AT+UDPCLOSE # 关闭UDP连接 + +AT+UDPREAD # 读取UDP数据 + +AT+UDPSEND # 发送UDP数据 + +AT+UDPSETUP # 建立UDP连接 + +AT+UDPTRANS # UDP透传模式 + +AT+CESQ # 扩展信号质量 + +AT+CPSERVICE # 【未匹配到】 + +AT+ENPWRSAVE # 【未匹配到】 + +AT+NFTCHIPTYPE # 【未匹配到】 + +AT+NFTFBACKUP # 【未匹配到】 + +AT+NFTRCAL # 【未匹配到】 + +AT+NFTRCREG # 【未匹配到】 + +AT+NFTRCSQ # 【未匹配到】 + +AT+NFTRFBAK # 【未匹配到】 + +AT+NFTRFIT # 【未匹配到】 + +AT+NWENPWRSAVE # 【未匹配到】 + +AT+QCNVERSION # 【未匹配到】 + +AT+READADC # 【未匹配到】 + +AT+CCID # 读取ICCID (SIM卡序列号) - 同AT+ICCID + +AT+CNUM # 用户号码 + +AT+NWCCID # 【未匹配到】 + +AT+NWSIMCFG # 【未匹配到】 + +AT+NWSIMDET # 【未匹配到】 + +AT+NWSIMWRCNT # 【未匹配到】 + +AT+NWSIMWRCNTCTL # 【未匹配到】 + +AT+SIMCROSS # 【未匹配到】 + +AT+SIMHOTSWAP # 【未匹配到】 + +AT+NETSHAREACT # 【未匹配到】 + +AT+XIIC # 建立PDP链接 (PPP拨号: 1=连接,0=断开) + +AT+CGMM # 请求型号标识 + +AT+CGMR # 请求修订版本标识 + +AT+GMM # 请求型号标识 (同AT+CGMM) + +AT+GSN # 请求产品序列号 (同AT+CGSN) + +AT+HEAPINFO # 【未匹配到】 + +AT+NETSHAREMODE # 【未匹配到】 + +AT+BANDLOCK # 【未匹配到】 + +AT+MYCELLINFO # 【未匹配到】 + +AT+MYCGED # 【未匹配到】 + +AT+MYLACID # 【未匹配到】 + +AT+MYNETINFO # 【未匹配到】 + +AT+MYSYSINFO # 【未匹配到】 + +AT+MYSYSINFOURC # 【未匹配到】 + +AT+MYURCSYSINFO # 【未匹配到】 + +AT+NBANDLOCK # 【未匹配到】 + +AT+NETDMSG # 【未匹配到】 + +AT+NETMSG # 【未匹配到】 + +AT+NFREQLOCK # 【未匹配到】 + +AT+NRSP # 【未匹配到】 + +AT+NSTGETRSSI # 【未匹配到】 + +AT+NWENG # 【未匹配到】 + +AT+NWRFTEST # 【未匹配到】 + +AT&F # 恢复出厂设置 + +AT&W # 存储当前配置 + +AT&V # 显示当前配置 + +ATD # 拨号 (标准PPP拨号命令) + +ATH # 挂断 (挂断当前连接) + +ATS0 # 自动应答设置 + +ATE # 回显控制 (ATE0=关闭回显,ATE1=开启回显) + +ATO # 返回在线模式 + +ATI # 请求标识信息 + +OK # 命令执行成功响应 + +# 统计信息: +# 总命令数: 400 +# 已匹配标准AT命令: ~60个 (3GPP标准命令) +# 已匹配Neoway扩展命令: ~15个 (如XIIC, TCPSETUP等) +# 未匹配: ~325个 (大部分是Neoway专有扩展命令,以N开头) +# +# 说明: +# 1. 标准3GPP AT命令(如AT+CFUN, AT+CSQ等)在手册中都有详细说明 +# 2. Neoway扩展的TCP/UDP相关命令(TCPSETUP, UDPSETUP等)也有说明 +# 3. 大量以"AT+N"开头的命令是Neoway专有扩展,手册中可能未包含 +# 4. 部分命令可能是内部测试或调试用途 +# +# 重要命令说明: +# - AT+XIIC: Neoway专有的PPP拨号命令,等同于标准的ATD*99***1# +# - AT+CFUN: 模组功能设置,1=全功能,4=飞行模式 +# - AT+CREG: 网络注册状态查询 +# - AT+CGDCONT: PDP上下文设置,用于配置APN +# - AT+TCPSETUP/UDPSETUP: Neoway专有的TCP/UDP连接建立命令 \ No newline at end of file diff --git a/code/sdk/zhihui/ppp/doc/cesq_implementation_summary.md b/code/sdk/zhihui/ppp/doc/cesq_implementation_summary.md new file mode 100644 index 000000000..0519ecba6 --- /dev/null +++ b/code/sdk/zhihui/ppp/doc/cesq_implementation_summary.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/code/sdk/zhihui/ppp/doc/signal_quality_assessment.md b/code/sdk/zhihui/ppp/doc/signal_quality_assessment.md new file mode 100644 index 000000000..0519ecba6 --- /dev/null +++ b/code/sdk/zhihui/ppp/doc/signal_quality_assessment.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/code/sdk/zhihui/ppp/doc/stub_functions_readme.md b/code/sdk/zhihui/ppp/doc/stub_functions_readme.md new file mode 100644 index 000000000..0519ecba6 --- /dev/null +++ b/code/sdk/zhihui/ppp/doc/stub_functions_readme.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/code/sdk/zhihui/ppp/example/api_shell.c b/code/sdk/zhihui/ppp/example/api_shell.c index 7582a1eea..482378afd 100644 --- a/code/sdk/zhihui/ppp/example/api_shell.c +++ b/code/sdk/zhihui/ppp/example/api_shell.c @@ -105,7 +105,7 @@ struct ifconfig_option { }; static char result_data[256] = {0}; -static char hostname[20] = {0}; +static char hostname[128] = {0}; void get_ping_hostname(char *databuf,uint8_t len) { diff --git a/code/sdk/zhihui/ppp/example/ppp_at_cmd.c b/code/sdk/zhihui/ppp/example/ppp_at_cmd.c index 4000de9c6..3ceb0ff57 100644 --- a/code/sdk/zhihui/ppp/example/ppp_at_cmd.c +++ b/code/sdk/zhihui/ppp/example/ppp_at_cmd.c @@ -1,4 +1,3 @@ - #include "at_cmd_api.h" #include "pm_control.h" #include "ppp_at_cmd.h" @@ -1299,6 +1298,26 @@ static errcode_t at_ppp_check_data_flow(uint8_t *para, uint32_t paraLen) return ERRCODE_SUCC; } +/** + * @brief AT^PPPSIGNALINFO - 获取网络信号信息 + */ +static errcode_t at_ppp_get_signal_info(uint8_t *para, uint32_t paraLen) +{ + (void)para; + (void)paraLen; + + PRINT("[PPP_INFO]PPP SIGNAL INFO: Getting network signal information...\r\n"); + + errcode_t ret = ppp_get_network_signal_info(); + if (ret == ERRCODE_SUCC) { + PRINT("[PPP_INFO]PPP SIGNAL INFO: Network signal information retrieved successfully\r\n"); + } else { + PRINT("[PPP_ERR]PPP SIGNAL INFO: Failed to get network signal information, error: %d\r\n", ret); + } + + return ret; +} + /* UART回调测试指令 */ static errcode_t at_ppp_test_uart_callback(uint8_t *para, uint32_t paraLen) { @@ -1622,6 +1641,7 @@ static const at_cmd_table_t g_ppp_cmd[] = { { (char *)"AT^STOPWSMULTI", at_ws_multi_test_stop, (char *)" " }, { (char *)"AT^WSMULTISTATUS", at_ws_multi_test_status, (char *)" " }, #endif + { (char *)"AT^PPPSIGNALINFO", at_ppp_get_signal_info, (char *)" " }, }; at_cmd_table_t *get_ppp_cmd_table(uint32_t *cmd_count) diff --git a/code/sdk/zhihui/ppp/example/ppp_example.c b/code/sdk/zhihui/ppp/example/ppp_example.c index 5599d3685..cc4c357f4 100644 --- a/code/sdk/zhihui/ppp/example/ppp_example.c +++ b/code/sdk/zhihui/ppp/example/ppp_example.c @@ -40,10 +40,10 @@ int ppp_env_init(void) /* 1. 配置PPP拨号参数 */ ppp_config_t config = { - .apn = "cmnet", // 中国移动APN + .apn = "CMIOTZSZCGRE.GD", // 中国移动APN cmnet .username = "", // 用户名(通常为空) .password = "", // 密码(通常为空) - .baudrate = 2000000, // 2M波特率 + .baudrate = PPP_UART_BAUDRATE, // 2M波特率 .auto_baudrate = true, // 启用自动波特率检测 .dial_timeout = 30000, // 30秒拨号超时 .retry_count = 3 // 重试3次 diff --git a/code/sdk/zhihui/ppp/example/ppp_power_example.c b/code/sdk/zhihui/ppp/example/ppp_power_example.c deleted file mode 100644 index 7858ab197..000000000 --- a/code/sdk/zhihui/ppp/example/ppp_power_example.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * @brief PPP模块电源控制使用示例 - * @description 演示如何使用PPP模块的电源控制功能 - * Copyright (c) CompanyNameMagicTag 2024-2024. All rights reserved. - */ - -#include "ppp_api.h" -#include "ppp_power_ctl.h" -#include "ppp_debug.h" -#include "osal_debug.h" -#include "platform_core.h" - -// 外部声明cat1Service兼容接口(在ppp_cat1_api.c中实现) -extern void cat1_api_enable_cat1(bool isopen); -extern bool cat1_api_is_cat1_enabled(void); -extern uint8_t cat1_api_runtime_get_cat1_powerstat(void); - -/** - * @brief PPP电源控制示例 - */ -void ppp_power_control_example(void) -{ - PPP_DEBUG_PRINT("=== PPP Power Control Example ===\n"); - - // 1. 配置4G控制引脚 - ppp_ctl_pin_4g_t pin_config = { - .bat_pin = S_AGPIO_L17, - .bat_pin_en_value = 1, - .pwr_pin = S_AGPIO_L23, - .pwr_pin_en_value = 1, - .reset_pin = S_AGPIO_L28, - .reset_pin_en_value = 0, - .ring_pin = PIN_NONE, - .ring_pin_en_value = 0, - .wakemodem_pin = PIN_NONE, - .wakemodem_pin_en_value = 0 - }; - - // 2. 注册控制引脚配置 - errcode_t ret = ppp_register_ctl_pin(&pin_config); - if (ret != ERRCODE_SUCC) { - PPP_DEBUG_PRINT("Failed to register control pins: %d\n", ret); - return; - } - - PPP_DEBUG_PRINT("Control pins registered successfully\n"); - - // 3. 使用PPP专用接口控制4G电源 - PPP_DEBUG_PRINT("Testing PPP-specific power control...\n"); - - // 开启4G电源 - ppp_api_enable_cat1(true); - osal_msleep(1000); - - // 检查电源状态 - bool enabled = ppp_api_is_cat1_enabled(); - PPP_DEBUG_PRINT("4G power status (PPP): %s\n", enabled ? "ON" : "OFF"); - - osal_msleep(2000); - - // 关闭4G电源 - ppp_api_enable_cat1(false); - osal_msleep(1000); - - enabled = ppp_api_is_cat1_enabled(); - PPP_DEBUG_PRINT("4G power status (PPP): %s\n", enabled ? "ON" : "OFF"); - - // 4. 使用兼容接口控制4G电源(推荐方式) - PPP_DEBUG_PRINT("Testing compatible power control interface...\n"); - - // 开启4G电源(通过兼容接口) - cat1_api_enable_cat1(true); - osal_msleep(1000); - - // 检查电源状态(通过兼容接口) - enabled = cat1_api_is_cat1_enabled(); - PPP_DEBUG_PRINT("4G power status (Compatible): %s\n", enabled ? "ON" : "OFF"); - - // 获取运行时状态 - uint8_t power_stat = cat1_api_runtime_get_cat1_powerstat(); - PPP_DEBUG_PRINT("4G runtime power status: %d\n", power_stat); - - osal_msleep(2000); - - // 关闭4G电源(通过兼容接口) - cat1_api_enable_cat1(false); - osal_msleep(1000); - - enabled = cat1_api_is_cat1_enabled(); - PPP_DEBUG_PRINT("4G power status (Compatible): %s\n", enabled ? "ON" : "OFF"); - - PPP_DEBUG_PRINT("=== PPP Power Control Example Completed ===\n"); -} - -/** - * @brief PPP完整拨号示例(包含电源控制) - */ -void ppp_dial_with_power_example(void) -{ - PPP_DEBUG_PRINT("=== PPP Dial with Power Control Example ===\n"); - - // 1. 初始化PPP配置 - ppp_config_t config = { - .apn = "cmnet", - .username = "", - .password = "", - .baudrate = 115200, - .auto_baudrate = true, - .dial_timeout = 30000, - .retry_count = 3 - }; - - // 2. 初始化PPP模块 - errcode_t ret = zhihui_ppp_init(&config); - if (ret != ERRCODE_SUCC) { - PPP_DEBUG_PRINT("Failed to initialize PPP: %d\n", ret); - return; - } - - PPP_DEBUG_PRINT("PPP module initialized\n"); - - // 3. 启动PPP拨号(内部会自动控制4G电源) - ret = ppp_start_dial(); - if (ret != ERRCODE_SUCC) { - PPP_DEBUG_PRINT("Failed to start PPP dial: %d\n", ret); - zhihui_ppp_deinit(); - return; - } - - PPP_DEBUG_PRINT("PPP dial started\n"); - - // 4. 等待连接建立(实际应用中应该通过事件回调处理) - PPP_DEBUG_PRINT("Waiting for connection...\n"); - osal_msleep(10000); - - // 5. 检查连接状态 - ppp_state_t state = ppp_get_state(); - PPP_DEBUG_PRINT("PPP state: %d\n", state); - - // 6. 获取连接信息 - ppp_connection_info_t conn_info; - ret = ppp_get_connection_info(&conn_info); - if (ret == ERRCODE_SUCC) { - PPP_DEBUG_PRINT("Connection info retrieved\n"); - PPP_DEBUG_PRINT(" Connected: %s\n", conn_info.connected ? "Yes" : "No"); - PPP_DEBUG_PRINT(" Local IP: 0x%08X\n", conn_info.local_ip); - PPP_DEBUG_PRINT(" Remote IP: 0x%08X\n", conn_info.remote_ip); - PPP_DEBUG_PRINT(" Primary DNS: 0x%08X\n", conn_info.primary_dns); - PPP_DEBUG_PRINT(" MTU: %d\n", conn_info.mtu); - } - - // 7. 保持连接一段时间 - PPP_DEBUG_PRINT("Keeping connection for 30 seconds...\n"); - osal_msleep(30000); - - // 8. 停止PPP连接(内部会自动控制4G电源) - ret = ppp_stop_dial(); - if (ret != ERRCODE_SUCC) { - PPP_DEBUG_PRINT("Failed to stop PPP dial: %d\n", ret); - } else { - PPP_DEBUG_PRINT("PPP dial stopped\n"); - } - - // 9. 去初始化PPP模块 - zhihui_ppp_deinit(); - PPP_DEBUG_PRINT("PPP module deinitialized\n"); - - PPP_DEBUG_PRINT("=== PPP Dial with Power Control Example Completed ===\n"); -} - -/** - * @brief 主函数示例 - */ -int main(void) -{ - // 系统初始化(根据实际系统调整) - // system_init(); - - PPP_DEBUG_PRINT("Starting PPP power control examples...\n"); - - // 运行电源控制示例 - ppp_power_control_example(); - - osal_msleep(5000); - - // 运行完整拨号示例 - ppp_dial_with_power_example(); - - PPP_DEBUG_PRINT("All examples completed\n"); - - return 0; -} \ No newline at end of file diff --git a/code/sdk/zhihui/ppp/include/ppp_api.h b/code/sdk/zhihui/ppp/include/ppp_api.h index 103bfc488..951c5caff 100644 --- a/code/sdk/zhihui/ppp/include/ppp_api.h +++ b/code/sdk/zhihui/ppp/include/ppp_api.h @@ -260,6 +260,12 @@ ppp_error_t ppp_lwip_stop_receive_thread(void); */ bool ppp_lwip_is_receive_thread_running(void); +/** + * @brief 获取并显示网络信号信息 + * @return ERRCODE_SUCC-成功,其他-失败 + */ +errcode_t ppp_get_network_signal_info(void); + #ifdef __cplusplus } #endif diff --git a/code/sdk/zhihui/ppp/include/ppp_at_handler.h b/code/sdk/zhihui/ppp/include/ppp_at_handler.h index 26d7f7b5f..3400529b3 100644 --- a/code/sdk/zhihui/ppp/include/ppp_at_handler.h +++ b/code/sdk/zhihui/ppp/include/ppp_at_handler.h @@ -87,6 +87,28 @@ bool ppp_at_get_auto_baudrate_mode(void); */ ppp_error_t ppp_at_test_communication(void); +/** + * @brief 网络信号信息结构体 (基于AT+CESQ命令) + */ +typedef struct { + // CESQ命令的信号参数 + int16_t rxlev; // GSM信号接收功率 (0-63, 99=无效) + int16_t ber; // 误码率 (0-7, 99=无效) + int16_t rscp; // UMTS下行载波干扰比率 (0-96, 255=无效) + int16_t ecno; // UMTS下行载波干扰比率 (0-49, 255=无效) + int16_t rsrq; // LTE参考信号质量 (0-34, 255=无效) + int16_t rsrp; // LTE参考信号接收功率 (0-97, 255=无效) + + bool valid; // 数据是否有效 +} ppp_network_signal_info_t; + +/** + * @brief 获取网络信号信息 + * @param info 信号信息结构体指针 + * @return 错误码 + */ +ppp_error_t ppp_at_get_network_signal_info(ppp_network_signal_info_t *info); + #ifdef __cplusplus } #endif diff --git a/code/sdk/zhihui/ppp/include/ppp_config.h b/code/sdk/zhihui/ppp/include/ppp_config.h index 040b28c85..a2f97043e 100644 --- a/code/sdk/zhihui/ppp/include/ppp_config.h +++ b/code/sdk/zhihui/ppp/include/ppp_config.h @@ -27,8 +27,10 @@ extern "C" { #define SIO_UART_IRQ_NUM UART_0_IRQN // UART IRQ引脚 #endif +#define PPP_UART_BAUDRATE 2000000 + /* 支持的波特率列表(自适应模式) */ -#define PPP_BAUDRATE_AUTO_LIST {2000000, 9600, 57600, 115200 } +#define PPP_BAUDRATE_AUTO_LIST {9600, 57600, 115200, 921600} #define PPP_BAUDRATE_AUTO_COUNT 4 /* 支持的固定波特率列表 */ @@ -61,7 +63,7 @@ extern "C" { /* 调试配置 */ #define PPP_DEBUG_ENABLE 1 // 启用调试输出 -#define PPP_DEBUG_LEVEL PPP_DEBUG_LEVEL_WARN // 默认只显示警告和错误 (1=ERROR, 2=WARN, 3=INFO, 4=DEBUG) +#define PPP_DEBUG_LEVEL PPP_DEBUG_LEVEL_DEBUG // 默认只显示警告和错误 (1=ERROR, 2=WARN, 3=INFO, 4=DEBUG) /* * 调试级别说明: diff --git a/code/sdk/zhihui/ppp/src/ppp_api.c b/code/sdk/zhihui/ppp/src/ppp_api.c index e6ed97828..a5ed481b6 100644 --- a/code/sdk/zhihui/ppp/src/ppp_api.c +++ b/code/sdk/zhihui/ppp/src/ppp_api.c @@ -36,32 +36,19 @@ extern void cat1_api_enable_cat1(bool isopen); static void ppp_check_and_update_state(void); errcode_t ppp_api_get_ppp_netif_name(char* netif_name, uint32_t buffer_size); -/** - * @brief 初始化PPP模块 - */ -errcode_t zhihui_ppp_init(const ppp_config_t *config) -{ - if (!config) { - PPP_DEBUG_PRINT("PPP init: invalid config parameter\n"); - return ERRCODE_FAIL; - } - if (g_ppp_state != PPP_STATE_IDLE) { - PPP_DEBUG_PRINT("PPP init: already initialized, current state: %d\n", g_ppp_state); + +errcode_t ppp_api_power_init(void) +{ + if (g_4g_power_initialized) { + PPP_DEBUG_PRINT("4G power already initialized\n"); return ERRCODE_SUCC; } - PPP_DEBUG_PRINT("Initializing PPP module with zhihui API\n"); - - // 保存用户配置 - memcpy_s(&g_ppp_config, sizeof(ppp_config_t), config, sizeof(ppp_config_t)); - // 1. GPIO初始化 - PPP_DEBUG_PRINT("Step 1: Initializing GPIO system\n"); - ppp_api_gpio_init(); - + // 2. CAT1电源操作 - PPP_DEBUG_PRINT("Step 2: Configuring and enabling CAT1 power\n"); + PPP_DEBUG_PRINT("Step 1: Configuring CAT1 power pins\n"); // 配置4G电源控制引脚 ppp_ctl_pin_4g_t pin_config = { @@ -70,40 +57,93 @@ errcode_t zhihui_ppp_init(const ppp_config_t *config) .pwr_pin = S_AGPIO_L23, .pwr_pin_en_value = 1, .reset_pin = S_AGPIO_L24, - .reset_pin_en_value = 0, - .ring_pin = PIN_NONE, - .ring_pin_en_value = 0, - .wakemodem_pin = S_MGPIO22, - .wakemodem_pin_en_value = 1 + .reset_pin_en_value = 1, //电路中 控制gpio拉高,reset才拉低 + .ring_pin = S_MGPIO21, //CTS cat1 wakeup mcu + .ring_pin_en_value = 2, //2 双边沿中断 , 1 上升沿中断 , 0 下降沿中断 + .wakemodem_pin = S_MGPIO22, //RTS mcu wakeup cat1 + .wakemodem_pin_en_value = 1 //1 唤醒cat1 , 0 休眠cat1 }; - + // 注册4G电源控制引脚配置 - errcode_t power_ret = ppp_register_ctl_pin(&pin_config); - if (power_ret != ERRCODE_SUCC) { - PPP_DEBUG_PRINT("Failed to register 4G power control pins: %d\n", power_ret); - PPP_DEBUG_PRINT("Continuing without power control...\n"); - g_4g_power_initialized = false; - } else { - PPP_DEBUG_PRINT("4G power control pins registered successfully\n"); - g_4g_power_initialized = true; - + ppp_register_ctl_pin(&pin_config); + + PPP_DEBUG_PRINT("Step 2: Initializing GPIO system\n"); + ppp_api_gpio_init(); + + PPP_DEBUG_PRINT("4G power control pins registered successfully\n"); + g_4g_power_initialized = true; + return ERRCODE_SUCC; +} + +errcode_t ppp_api_power_control(bool is_open) +{ + if (is_open) { // 启用4G电源 PPP_DEBUG_PRINT("Enabling 4G module power...\n"); cat1_api_enable_cat1(true); - osal_msleep(2000); // 等待电源稳定 - + osal_msleep(500); + // 唤醒4G模块 PPP_DEBUG_PRINT("Waking up 4G module...\n"); cat1_api_wakeup_cat1(true); - osal_msleep(1000); // 等待唤醒完成 - - // 检查电源状态 - bool power_enabled = cat1_api_is_cat1_enabled(); - uint8_t power_stat = cat1_api_runtime_get_cat1_powerstat(); - PPP_DEBUG_PRINT("4G power status: %s (runtime stat: %d)\n", - power_enabled ? "ON" : "OFF", power_stat); + + } else { + PPP_DEBUG_PRINT("Sleeping 4G module power...\n"); + // 唤醒4G模块 + cat1_api_wakeup_cat1(false); + osal_msleep(500); + // 启用4G电源 + PPP_DEBUG_PRINT("Disabling 4G module power...\n"); + cat1_api_enable_cat1(false); + } + + // 检查电源状态 + bool power_enabled = cat1_api_is_cat1_enabled(); + uint8_t power_stat = cat1_api_runtime_get_cat1_powerstat(); + PPP_DEBUG_PRINT("4G power status: %s (runtime stat: %d)\n", + power_enabled ? "ON" : "OFF", power_stat); + return ERRCODE_SUCC; +} + + + +/** + * @brief 初始化PPP模块 + * + * 1. 初始化电源控制模块 + * 2. 打开4G电源 + * 3. 等待5秒,确保模块稳定 + * 4. 初始化串口,设置为AT模式 + * 5. 测试AT指令通信 + * - 如果默认波特率下AT指令成功,配置环境变量并返回成功 + * - 否则,尝试自动波特率握手,重置到默认波特率下工作 + * - 若仍失败,则初始化失败 + */ +errcode_t zhihui_ppp_init(const ppp_config_t *config) +{ + if (!config) { + PPP_DEBUG_PRINT("PPP init: invalid config parameter\n"); + return ERRCODE_FAIL; } + if (g_ppp_state != PPP_STATE_IDLE) { + PPP_DEBUG_PRINT("PPP init: already initialized, current state: %d\n", g_ppp_state); + return ERRCODE_SUCC; + } + + PPP_DEBUG_PRINT("Initializing PPP module with zhihui API\n"); + + // 保存用户配置 + memcpy_s(&g_ppp_config, sizeof(ppp_config_t), config, sizeof(ppp_config_t)); + + ppp_api_power_init(); + + ppp_api_power_control(true); + + // 额外等待时间,让调制解调器完全稳定(特别是在硬件复位后) + PPP_DEBUG_PRINT("Waiting for modem stabilization after power control...\n"); + osal_msleep(5000); // 等待5秒让调制解调器完全稳定 + // 3. UART初始化 PPP_DEBUG_PRINT("Step 3: Initializing UART for AT mode\n"); ppp_serial_config_t serial_config = { @@ -117,6 +157,7 @@ errcode_t zhihui_ppp_init(const ppp_config_t *config) .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); @@ -131,19 +172,6 @@ errcode_t zhihui_ppp_init(const ppp_config_t *config) goto init_failed; } - // 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"); - } - // 5. 默认工作在AT指令模式 PPP_DEBUG_PRINT("Step 5: Ensuring default AT command mode\n"); ret = ppp_serial_switch_to_at_mode(); @@ -153,7 +181,33 @@ errcode_t zhihui_ppp_init(const ppp_config_t *config) } 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"); + } + g_ppp_state = PPP_STATE_INITIALIZED; @@ -163,13 +217,7 @@ errcode_t zhihui_ppp_init(const ppp_config_t *config) init_failed: // 初始化失败,关闭4G电源 - if (g_4g_power_initialized) { - PPP_DEBUG_PRINT("Disabling 4G power due to initialization failure\n"); - cat1_api_wakeup_cat1(false); - osal_msleep(500); - cat1_api_enable_cat1(false); - g_4g_power_initialized = false; - } + // ppp_api_power_control(false); return ERRCODE_FAIL; } @@ -386,27 +434,68 @@ error_recovery_at_mode: // 6. 重新初始化AT处理器 PPP_DEBUG_INFO("Reinitializing AT handler..."); - ret = ppp_at_handler_init(0); // 使用UART bus 0 + ret = ppp_at_handler_init(SIO_UART_BUS); // 使用UART bus 0 if (ret != PPP_ERR_OK) { PPP_DEBUG_ERROR("Failed to reinitialize AT handler: %d", ret); return ERRCODE_FAIL; } // 7. 验证AT模式是否正常工作 - PPP_DEBUG_INFO("Verifying AT mode..."); - ret = ppp_at_test_communication(); - if (ret != PPP_ERR_OK) { - PPP_DEBUG_WARN("AT communication test failed: %d", ret); - // 尝试重置串口 - PPP_DEBUG_INFO("Attempting serial reset..."); + PPP_DEBUG_INFO("Verifying AT mode with enhanced recovery..."); + + // 多次尝试AT通信,每次尝试前清理串口缓冲区 + bool at_communication_ok = false; + for (int attempt = 1; attempt <= 5; attempt++) { + PPP_DEBUG_INFO("AT communication attempt %d/5...", attempt); + + // 清理串口缓冲区 ppp_serial_reset(); - osal_msleep(100); + osal_msleep(500); + + // 尝试AT通信 ret = ppp_at_test_communication(); - if (ret != PPP_ERR_OK) { - PPP_DEBUG_ERROR("Serial reset failed, AT communication still broken"); + if (ret == PPP_ERR_OK) { + PPP_DEBUG_INFO("AT communication successful on attempt %d", attempt); + at_communication_ok = true; + break; + } else { + PPP_DEBUG_WARN("AT communication failed on attempt %d: %d", attempt, ret); + if (attempt < 5) { + // 在重试之前,尝试发送一些基本的AT命令来"唤醒"调制解调器 + PPP_DEBUG_INFO("Sending wake-up AT commands..."); + uint8_t at_wake[] = "AT\r\n"; + ppp_serial_write(at_wake, sizeof(at_wake)-1); + osal_msleep(1000); + + // 清理可能的响应 + uint8_t dummy_buffer[128]; + uint32_t dummy_read = 0; + ppp_serial_read(dummy_buffer, sizeof(dummy_buffer), &dummy_read); + + osal_msleep(1000); // 等待1秒再重试 + } } } + if (!at_communication_ok) { + PPP_DEBUG_ERROR("AT communication failed after 5 attempts - modem may need manual intervention"); + // 不返回错误,继续执行,让上层决定如何处理 + } + + // 8. 发送AT挂断命令确保PPP连接完全断开 + if (at_communication_ok) { + PPP_DEBUG_INFO("Sending AT hangup command to ensure PPP disconnection..."); + ppp_error_t hangup_ret = ppp_at_hangup_ppp(); + if (hangup_ret != PPP_ERR_OK) { + PPP_DEBUG_WARN("AT hangup command failed: %d", hangup_ret); + // 不作为致命错误,因为PPP可能已经通过其他方式断开 + } else { + PPP_DEBUG_INFO("AT hangup command completed successfully"); + } + } else { + PPP_DEBUG_WARN("Skipping AT hangup command due to communication issues"); + } + PPP_DEBUG_CRITICAL("=== PPP Stop Dial Completed ==="); // 设置最终状态为已初始化 @@ -426,6 +515,9 @@ errcode_t ppp_stop_dial(void) // 设置状态为断开中 g_ppp_state = PPP_STATE_DISCONNECTING; + ppp_error_t ret = PPP_ERR_OK; // 声明ret变量 + bool at_communication_ok = false; // 声明AT通信状态变量 + // 1. 首先停止PPP数据接收线程(在切换串口模式之前) PPP_DEBUG_INFO("Stopping PPP receive thread..."); ppp_lwip_stop_receive_thread(); @@ -443,9 +535,63 @@ errcode_t ppp_stop_dial(void) PPP_DEBUG_INFO("Cleaning up lwIP PPP resources..."); ppp_lwip_deinit(); + // 4.5. 发送PPP标准挂断序列 - 通知调制解调器退出PPP数据模式 + PPP_DEBUG_INFO("Sending PPP standard hangup sequence to modem..."); + + // 等待确保前面的操作完成 + osal_msleep(1000); + + // // 方法1:发送+++转义序列切换调制解调器到命令模式 + // PPP_DEBUG_INFO("Sending escape sequence (+++) to switch modem to command mode..."); + // const char escape_seq[] = "+++"; + // ppp_error_t escape_ret = ppp_serial_write((uint8_t*)escape_seq, strlen(escape_seq)); + // if (escape_ret == PPP_ERR_OK ) { + // PPP_DEBUG_INFO("Escape sequence sent successfully"); + // osal_msleep(2000); // 增加等待时间到2秒 + + // // 尝试读取调制解调器响应 + // uint8_t response_buffer[64]; + // uint32_t bytes_read = 0; + // ppp_serial_read(response_buffer, sizeof(response_buffer), &bytes_read); + // if (bytes_read > 0) { + // PPP_DEBUG_INFO("Modem response to escape sequence: %u bytes", bytes_read); + // } else { + // PPP_DEBUG_WARN("No immediate response from modem after escape sequence"); + // } + + // // 发送N706A专用的断开命令 + // PPP_DEBUG_INFO("Sending N706A hangup command (AT+XIIC=0)..."); + // uint8_t xiic_cmd[] = "AT+XIIC=0\r\n"; + // ppp_serial_write(xiic_cmd, sizeof(xiic_cmd)-1); + // osal_msleep(1000); + + // // 读取XIIC命令的响应 + // ppp_serial_read(response_buffer, sizeof(response_buffer), &bytes_read); + // if (bytes_read > 0) { + // PPP_DEBUG_INFO("Modem response to XIIC=0: %u bytes", bytes_read); + // } + // } else { + // PPP_DEBUG_WARN("Failed to send escape sequence to modem"); + // } + + // 方法2:如果软件方法失败,使用硬件复位确保调制解调器状态 + PPP_DEBUG_INFO("Applying hardware reset to ensure clean modem state..."); + + // 使用4G电源控制进行复位 + PPP_DEBUG_INFO("Performing gentle 4G modem reset..."); + + // 第二步:短暂断电复位(更温和的方式) + PPP_DEBUG_INFO("Step 2: Brief power cycle..."); + ppp_api_cat1_reset(1); + osal_msleep(500); // 减少断电时间到1秒 + ppp_api_cat1_reset(0); + osal_msleep(5000); // 等待2秒让调制解调器启动 + + PPP_DEBUG_INFO("Gentle 4G modem reset completed - modem should be stable now"); + // 5. 现在安全地切换串口回AT命令模式 PPP_DEBUG_INFO("Switching serial to AT mode..."); - ppp_error_t ret = ppp_serial_switch_to_at_mode(); + ret = ppp_serial_switch_to_at_mode(); if (ret != PPP_ERR_OK) { PPP_DEBUG_ERROR("Failed to switch to AT mode: %d", ret); return ret; @@ -453,27 +599,68 @@ errcode_t ppp_stop_dial(void) // 6. 重新初始化AT处理器 PPP_DEBUG_INFO("Reinitializing AT handler..."); - ret = ppp_at_handler_init(0); // 使用UART bus 0 + ret = ppp_at_handler_init(SIO_UART_BUS); // 使用UART bus 0 if (ret != PPP_ERR_OK) { PPP_DEBUG_ERROR("Failed to reinitialize AT handler: %d", ret); return ret; } // 7. 验证AT模式是否正常工作 - PPP_DEBUG_INFO("Verifying AT mode..."); - ret = ppp_at_test_communication(); - if (ret != PPP_ERR_OK) { - PPP_DEBUG_WARN("AT communication test failed: %d", ret); - // 尝试重置串口 - PPP_DEBUG_INFO("Attempting serial reset..."); + PPP_DEBUG_INFO("Verifying AT mode with enhanced recovery..."); + + // 多次尝试AT通信,每次尝试前清理串口缓冲区 + at_communication_ok = false; + for (int attempt = 1; attempt <= 5; attempt++) { + PPP_DEBUG_INFO("AT communication attempt %d/5...", attempt); + + // 清理串口缓冲区 ppp_serial_reset(); - osal_msleep(100); + osal_msleep(500); + + // 尝试AT通信 ret = ppp_at_test_communication(); - if (ret != PPP_ERR_OK) { - PPP_DEBUG_ERROR("Serial reset failed, AT communication still broken"); + if (ret == PPP_ERR_OK) { + PPP_DEBUG_INFO("AT communication successful on attempt %d", attempt); + at_communication_ok = true; + break; + } else { + PPP_DEBUG_WARN("AT communication failed on attempt %d: %d", attempt, ret); + if (attempt < 5) { + // 在重试之前,尝试发送一些基本的AT命令来"唤醒"调制解调器 + PPP_DEBUG_INFO("Sending wake-up AT commands..."); + uint8_t at_wake[] = "AT\r\n"; + ppp_serial_write(at_wake, sizeof(at_wake)-1); + osal_msleep(1000); + + // 清理可能的响应 + uint8_t dummy_buffer[128]; + uint32_t dummy_read = 0; + ppp_serial_read(dummy_buffer, sizeof(dummy_buffer), &dummy_read); + + osal_msleep(1000); // 等待1秒再重试 + } } } + if (!at_communication_ok) { + PPP_DEBUG_ERROR("AT communication failed after 5 attempts - modem may need manual intervention"); + // 不返回错误,继续执行,让上层决定如何处理 + } + + // 8. 发送AT挂断命令确保PPP连接完全断开 + if (at_communication_ok) { + PPP_DEBUG_INFO("Sending AT hangup command to ensure PPP disconnection..."); + ppp_error_t hangup_ret = ppp_at_hangup_ppp(); + if (hangup_ret != PPP_ERR_OK) { + PPP_DEBUG_WARN("AT hangup command failed: %d", hangup_ret); + // 不作为致命错误,因为PPP可能已经通过其他方式断开 + } else { + PPP_DEBUG_INFO("AT hangup command completed successfully"); + } + } else { + PPP_DEBUG_WARN("Skipping AT hangup command due to communication issues"); + } + PPP_DEBUG_CRITICAL("=== PPP Stop Dial Completed ==="); // 设置最终状态为已初始化 @@ -609,27 +796,17 @@ errcode_t zhihui_ppp_deinit(void) } // 2. 去初始化串口和AT处理器 - PPP_DEBUG_PRINT("Deinitializing serial and AT handler\n"); - ppp_at_handler_deinit(); - ppp_serial_deinit(); - - // 3. 关闭4G电源 - if (g_4g_power_initialized) { - PPP_DEBUG_PRINT("Disabling 4G module power\n"); - - // 让4G模块进入休眠状态 - PPP_DEBUG_PRINT("Putting 4G module to sleep\n"); - cat1_api_wakeup_cat1(false); - osal_msleep(500); - - // 关闭4G电源 - PPP_DEBUG_PRINT("Turning off 4G module power\n"); - cat1_api_enable_cat1(false); - osal_msleep(1000); - - g_4g_power_initialized = false; - PPP_DEBUG_PRINT("4G power disabled successfully\n"); - } + // PPP_DEBUG_PRINT("Deinitializing serial and AT handler\n"); + // ppp_at_handler_deinit(); + // ppp_serial_deinit(); + + // // 3. 关闭4G电源 + // PPP_DEBUG_INFO("Power off modem"); + // extern ppp_error_t ppp_at_poweroff_modem(uint8_t shutdown_type); + // ppp_error_t ret = ppp_at_poweroff_modem(0); + // if (ret != PPP_ERR_OK) { + // PPP_DEBUG_ERROR("Failed to power off modem"); + // } // 4. 清理资源 (void)memset_s(&g_ppp_config, sizeof(ppp_config_t), 0, sizeof(ppp_config_t)); @@ -2090,4 +2267,69 @@ static void ppp_check_and_update_state(void) (lwip_info.local_ip >> 24) & 0xFF); } } +} + +/** + * @brief 获取并显示网络信号信息 + * @return 错误码 + */ +errcode_t ppp_get_network_signal_info(void) +{ + if (g_ppp_state == PPP_STATE_IDLE) { + PPP_DEBUG_ERROR("PPP not initialized"); + return ERRCODE_FAIL; + } + + PPP_DEBUG_INFO("Getting network signal information..."); + + ppp_network_signal_info_t signal_info; + ppp_error_t ret = ppp_at_get_network_signal_info(&signal_info); + + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("Failed to get network signal information: %d", ret); + return ERRCODE_FAIL; + } + + if (!signal_info.valid) { + PPP_DEBUG_WARN("Network signal information is not valid"); + return ERRCODE_FAIL; + } + + // 输出格式化的信号信息摘要 + PPP_DEBUG_CRITICAL("=== Network Signal Summary (AT+CESQ) ==="); + + // 仅关注LTE关键参数: RSRQ和RSRP + if (signal_info.rsrq != 255 && signal_info.rsrp != 255 && + signal_info.rsrq >= 0 && signal_info.rsrq <= 49 && + signal_info.rsrp >= 0 && signal_info.rsrp <= 97) { + + // CESQ格式的RSRQ和RSRP转换 (使用正确公式) + float rsrq_db = (signal_info.rsrq - 94) / 10.0f; // (rsrq - 94)/10 + float rsrp_dbm = signal_info.rsrp - 140.0f; // rsrp - 140 + + PPP_DEBUG_CRITICAL("LTE Signal Quality:"); + PPP_DEBUG_CRITICAL(" RSRQ: %d (%.1f dB)", signal_info.rsrq, rsrq_db); + PPP_DEBUG_CRITICAL(" RSRP: %d (%.0f dBm)", signal_info.rsrp, rsrp_dbm); + + // 综合质量评估 (基于RSRQ和RSRP) + const char *overall_quality = "未知"; + if (rsrq_db >= -6.0 && rsrp_dbm >= -80) { + overall_quality = "LTE信号极佳 (质量和强度都优秀)"; + } else if (rsrq_db >= -9.0 && rsrp_dbm >= -90) { + overall_quality = "LTE信号良好 (质量和强度都稳定)"; + } else if (rsrq_db >= -12.0 && rsrp_dbm >= -100) { + overall_quality = "LTE信号一般 (质量和强度可用)"; + } else { + overall_quality = "LTE信号较差 (需要改善网络环境)"; + } + + PPP_DEBUG_CRITICAL("Overall LTE Quality: %s", overall_quality); + } else { + PPP_DEBUG_CRITICAL("LTE参数无效,无法评估信号质量"); + PPP_DEBUG_CRITICAL("RSRQ: %d, RSRP: %d", signal_info.rsrq, signal_info.rsrp); + } + + PPP_DEBUG_CRITICAL("=== End Signal Summary ==="); + + return ERRCODE_SUCC; } \ No newline at end of file diff --git a/code/sdk/zhihui/ppp/src/ppp_at_handler.c b/code/sdk/zhihui/ppp/src/ppp_at_handler.c index d9976691e..a11e2c42e 100644 --- a/code/sdk/zhihui/ppp/src/ppp_at_handler.c +++ b/code/sdk/zhihui/ppp/src/ppp_at_handler.c @@ -44,7 +44,7 @@ ppp_error_t ppp_at_handler_init(uint8_t uart_bus) } g_at_ctx.uart_bus = uart_bus; - g_at_ctx.current_baudrate = SIO_UART_BAUDRATE; + g_at_ctx.current_baudrate = PPP_UART_BAUDRATE; g_at_ctx.auto_baudrate_mode = true; /* 创建互斥锁 */ @@ -92,6 +92,12 @@ void ppp_at_handler_deinit(void) /** * @brief 执行波特率自适应握手 + * + * 进入自适应波特率,证明2000000没有正常工作,需要先reset,等5秒,开始设置自动握手的第一个波特率, + * 读取所有缓存数据丢掉,下达at指令,等待结果,重试3次,如果不成功,就设置第二个波特率,读取所有缓存数据丢掉, + * 下达at指令,等结果,重试3次,直至第三个波特率检测。如果都没有成功,则返回失败。 + * 如果任何一次at指令返回正确ok,直接在当前设置下,下达指 AT+IPR 配置 2000000 波特率,并返回成功。 + * 设置当前波特率为2000000,再次reset 模组,让其自动工作在 2000000波特率下。 */ ppp_error_t ppp_at_baudrate_handshake(void) { @@ -99,73 +105,91 @@ ppp_error_t ppp_at_baudrate_handshake(void) return PPP_ERR_INVALID_PARAM; } - PPP_DEBUG_INFO("Starting baudrate handshake"); - - /* 先发送一些字符清空缓冲区 */ - PPP_DEBUG_DEBUG("Clearing UART buffers..."); - const char *clear_cmd = "\r\n\r\n"; - uapi_uart_write(g_at_ctx.uart_bus, (const uint8_t *)clear_cmd, strlen(clear_cmd), 0); - osal_msleep(200); - - /* 清空接收缓冲区 */ - uint8_t dummy_buffer[256]; - while (uapi_uart_read(g_at_ctx.uart_bus, dummy_buffer, sizeof(dummy_buffer), 100) > 0) { - /* 继续清空 */ - } + PPP_DEBUG_INFO("Starting baudrate handshake (prove 2000000 not working, then try auto handshake)"); + + // 1. 先reset模组,证明2000000没有正常工作 + PPP_DEBUG_INFO("Resetting module to prove 2000000 baudrate is not working..."); + ppp_api_cat1_reset(1); + osal_msleep(50); + ppp_api_cat1_reset(0); + osal_msleep(5000); - /* 尝试自适应波特率列表 */ + // 2. 依次尝试自动波特率列表 for (int i = 0; i < PPP_BAUDRATE_AUTO_COUNT; i++) { uint32_t baudrate = g_auto_baudrates[i]; - - PPP_DEBUG_INFO("=== Trying Baudrate %u (attempt %d/%d) ===", baudrate, i + 1, PPP_BAUDRATE_AUTO_COUNT); - - /* 配置串口波特率 */ + PPP_DEBUG_INFO("=== Trying Baudrate %u (index %d/%d) ===", baudrate, i + 1, PPP_BAUDRATE_AUTO_COUNT); + + // 配置串口波特率 uart_attr_t uart_attr = { .baud_rate = baudrate, .data_bits = UART_DATA_BIT_8, .parity = UART_PARITY_NONE, .stop_bits = UART_STOP_BIT_1, }; - if (uapi_uart_set_attr(g_at_ctx.uart_bus, &uart_attr) != ERRCODE_SUCC) { PPP_DEBUG_WARN("Failed to set baudrate %u", baudrate); continue; } - PPP_DEBUG_INFO("UART configured for baudrate %u", baudrate); - /* 发送AT命令测试 */ - ppp_at_response_t response; - - /* 增加重试机制 */ + // 清空接收缓冲区 + PPP_DEBUG_DEBUG("Clearing UART RX buffer before AT test..."); + uint8_t dummy_buffer[256]; + int clear_cnt = 0; + while (uapi_uart_read(g_at_ctx.uart_bus, dummy_buffer, sizeof(dummy_buffer), 100) > 0) { + clear_cnt++; + } + if (clear_cnt > 0) { + PPP_DEBUG_DEBUG("Cleared %d RX buffer rounds", clear_cnt); + } + + // 3次重试AT ppp_error_t ret = PPP_ERR_AT_FAILED; - for (int retry = 0; retry < 1; retry++) { + for (int retry = 0; retry < 3; retry++) { PPP_DEBUG_INFO("--- AT Test at %u baud, retry %d/3 ---", baudrate, retry + 1); - ret = ppp_at_send_command("AT", "OK", 3000, &response); // 增加超时到3秒 - + + // 再次清空缓冲区,防止上次残留 + 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); + if (ret == PPP_ERR_OK) { PPP_DEBUG_INFO("AT command successful at baudrate %u", baudrate); - break; + + // 在当前波特率下,设置AT+IPR=2000000 + char ipr_cmd[32]; + snprintf_s(ipr_cmd, sizeof(ipr_cmd), sizeof(ipr_cmd) - 1, "AT+IPR=2000000"); + PPP_DEBUG_INFO("Setting module baudrate to 2000000 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 2000000 (AT+IPR)"); + return PPP_ERR_AT_FAILED; + } + + ppp_at_set_baudrate(PPP_UART_BAUDRATE); + + // 再次reset模组,让其自动工作在2000000波特率下 + PPP_DEBUG_INFO("Resetting module again to switch to 2000000 baudrate..."); + ppp_api_cat1_reset(1); + osal_msleep(50); + ppp_api_cat1_reset(0); + osal_msleep(5000); + PPP_DEBUG_INFO("Baudrate handshake successful, now at 2000000 baud"); + return PPP_ERR_OK; } else { - PPP_DEBUG_WARN("AT command failed at baudrate %u, retry %d (error: %d)", baudrate, retry + 1, ret); - } - - if (retry < 2) { - osal_msleep(500); // 重试间隔 + PPP_DEBUG_WARN("AT command failed at baudrate %u, retry %d/3 (error: %d)", baudrate, retry + 1, ret); + osal_msleep(500); } } - - if (ret == PPP_ERR_OK) { - g_at_ctx.current_baudrate = baudrate; - PPP_DEBUG_INFO("=== Baudrate handshake successful at %u ===", baudrate); - return PPP_ERR_OK; - } - - PPP_DEBUG_WARN("Baudrate %u failed, trying next...", baudrate); - osal_msleep(100); // 短暂延时后尝试下一个波特率 + + PPP_DEBUG_WARN("Baudrate %u failed after 3 retries, trying next...", baudrate); + osal_msleep(100); } - PPP_DEBUG_ERROR("Baudrate handshake failed"); + PPP_DEBUG_ERROR("Baudrate handshake failed: all baudrates tried, no success"); return PPP_ERR_AT_FAILED; } @@ -430,33 +454,8 @@ ppp_error_t ppp_at_complete_dial_sequence(const char *apn) 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); - - 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 %s, continuing with current rate", ipr_cmd); - // 不返回错误,继续执行 - } else { - 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命令确认调制解调器状态 + + // 发送一个简单的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"); @@ -504,20 +503,27 @@ ppp_error_t ppp_at_complete_dial_sequence(const char *apn) PPP_DEBUG_INFO("Network registration status: %s", response.response); } - // 5. 发送PPP拨号指令 (对应chat文件: OK 'ATD*99***2#' -> CONNECTED) + // 5. 发送PPP拨号指令 - 使用Neoway N706A特有的XIIC命令 + // 根据AT命令手册,应该使用AT+XIIC=1来建立PPP连接,而不是ATD*99***2# + #if 1 + PPP_DEBUG_INFO("Starting PPP connection using Neoway N706A ATD*99***2# command..."); ret = ppp_at_send_command("ATD*99***2#", "CONNECT", 30000, &response); if (ret != PPP_ERR_OK) { - PPP_DEBUG_ERROR("PPP dial command failed"); + PPP_DEBUG_ERROR("PPP connection command (ATD*99***2#) 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..."); - + PPP_DEBUG_INFO("PPP connection established successfully with ATD*99***2# command"); + #else + PPP_DEBUG_INFO("Starting PPP connection using Neoway N706A XIIC command..."); + ret = ppp_at_send_command("AT+XIIC=1", "OK", 30000, &response); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("PPP connection command (AT+XIIC=1) failed"); + return ret; + } + PPP_DEBUG_INFO("PPP connection established successfully with XIIC command"); + #endif // 等待调制解调器稳定 osal_msleep(1000); - // 发送一个空的AT命令来测试是否还在AT模式 // 如果还在AT模式,会有响应;如果在PPP模式,不会有响应 uint8_t test_cmd[] = "AT\r\n"; @@ -564,6 +570,33 @@ ppp_error_t ppp_at_complete_dial_sequence(const char *apn) PPP_DEBUG_INFO("Modem data mode verification completed"); return PPP_ERR_OK; } +/** + * @brief 发送AT关机指令,支持快速关机和正常关机 + * @param shutdown_type 关机类型: 0-快速关机, 1-正常流程关机 + * @return ppp_error_t + */ +ppp_error_t ppp_at_poweroff_modem(uint8_t shutdown_type) +{ + if (!g_at_ctx.initialized) { + return PPP_ERR_INVALID_PARAM; + } + + PPP_DEBUG_INFO("Sending AT+NWPWROFF=%d to power off modem", shutdown_type); + + char cmd[32]; + snprintf(cmd, sizeof(cmd), "AT+NWPWROFF=%d", shutdown_type); + + ppp_at_response_t response; + ppp_error_t ret = ppp_at_send_command(cmd, "OK", 10000, &response); + + if (ret == PPP_ERR_OK) { + PPP_DEBUG_INFO("Modem power off command sent successfully"); + } else { + PPP_DEBUG_ERROR("Failed to send modem power off command"); + } + ppp_power_off_cat1(); + return ret; +} /** * @brief 挂断PPP连接 @@ -574,29 +607,51 @@ ppp_error_t ppp_at_hangup_ppp(void) return PPP_ERR_INVALID_PARAM; } - PPP_DEBUG_INFO("Hanging up PPP connection"); - - /* 发送+++切换到命令模式 */ - osal_msleep(1000); // 等待1秒 - - const char *escape_seq = "+++"; - if (uapi_uart_write(g_at_ctx.uart_bus, (const uint8_t *)escape_seq, 3, 0) != 3) { - PPP_DEBUG_ERROR("Failed to send escape sequence"); - return PPP_ERR_UART; - } - - osal_msleep(1000); // 等待1秒 + PPP_DEBUG_INFO("Disconnecting PPP connection using Neoway N706A XIIC command"); - /* 发送ATH挂断命令 */ + /* 使用N706A特有的XIIC=0命令断开PPP连接 */ ppp_at_response_t response; - ppp_error_t ret = ppp_at_send_command("ATH", "OK", PPP_AT_CMD_TIMEOUT, &response); + ppp_error_t ret = ppp_at_send_command("AT+XIIC=0", "OK", 10000, &response); if (ret != PPP_ERR_OK) { - PPP_DEBUG_ERROR("Failed to hangup PPP connection"); - return ret; + PPP_DEBUG_ERROR("Failed to disconnect PPP connection using XIIC=0"); + + /* 如果XIIC=0失败,尝试传统的挂断方法作为备用 */ + PPP_DEBUG_WARN("Trying traditional hangup method as fallback..."); + + /* 发送+++切换到命令模式 */ + osal_msleep(1000); + + const char *escape_seq = "+++"; + if (uapi_uart_write(g_at_ctx.uart_bus, (const uint8_t *)escape_seq, 3, 0) != 3) { + PPP_DEBUG_ERROR("Failed to send escape sequence"); + return PPP_ERR_UART; + } + + osal_msleep(1000); + + /* 发送ATH挂断命令 */ + ret = ppp_at_send_command("ATH", "OK", PPP_AT_CMD_TIMEOUT, &response); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("Traditional hangup also failed"); + return ret; + } + PPP_DEBUG_INFO("Traditional hangup successful"); + } else { + PPP_DEBUG_INFO("PPP connection disconnected successfully using XIIC=0"); + + // 验证断开状态 + osal_msleep(500); + ret = ppp_at_send_command("AT+XIIC?", "OK", 5000, &response); + if (ret == PPP_ERR_OK) { + PPP_DEBUG_INFO("PPP disconnection status: %s", response.response); + if (strstr(response.response, "+XIIC: 0,") != NULL) { + PPP_DEBUG_INFO("PPP disconnection verified - connection closed"); + } + } } - PPP_DEBUG_INFO("PPP connection hung up"); + PPP_DEBUG_INFO("PPP connection hangup completed"); return PPP_ERR_OK; } @@ -791,4 +846,159 @@ static void ppp_at_timeout_handler(unsigned long data) { (void)data; PPP_DEBUG_WARN("AT command timeout"); -} \ No newline at end of file +} + +/** + * @brief 解析AT+CESQ响应 + * 参考N706A AT命令手册: +CESQ: ,,,,, + */ +static ppp_error_t ppp_parse_cesq_response(const char *response, ppp_network_signal_info_t *info) +{ + if (!response || !info) { + return PPP_ERR_INVALID_PARAM; + } + + memset_s(info, sizeof(ppp_network_signal_info_t), 0, sizeof(ppp_network_signal_info_t)); + + // 查找+CESQ:开头的行 + const char *cesq_line = strstr(response, "+CESQ:"); + if (!cesq_line) { + PPP_DEBUG_WARN("No +CESQ: found in response"); + return PPP_ERR_AT_FAILED; + } + + // 跳过"+CESQ:" + cesq_line += 6; + while (*cesq_line == ' ' || *cesq_line == '\t') cesq_line++; + + // +CESQ: ,,,,, + int rxlev = 99, ber = 99, rscp = 255, ecno = 255, rsrq = 255, rsrp = 255; + int parsed = sscanf(cesq_line, "%d,%d,%d,%d,%d,%d", &rxlev, &ber, &rscp, &ecno, &rsrq, &rsrp); + + if (parsed == 6) { + info->valid = true; + info->rxlev = rxlev; + info->ber = ber; + info->rscp = rscp; + info->ecno = ecno; + info->rsrq = rsrq; + info->rsrp = rsrp; + PPP_DEBUG_INFO("CESQ parsed successfully: rxlev=%d, ber=%d, rscp=%d, ecno=%d, rsrq=%d, rsrp=%d", + rxlev, ber, rscp, ecno, rsrq, rsrp); + return PPP_ERR_OK; + } else { + PPP_DEBUG_WARN("Failed to parse CESQ response, parsed: %d", parsed); + return PPP_ERR_AT_FAILED; + } +} + +/** + * @brief 获取网络信号信息 (AT+CESQ) + */ +ppp_error_t ppp_at_get_network_signal_info(ppp_network_signal_info_t *info) +{ + if (!g_at_ctx.initialized || !info) { + return PPP_ERR_INVALID_PARAM; + } + + PPP_DEBUG_INFO("Getting network signal information (AT+CESQ)..."); + + ppp_at_response_t response; + ppp_error_t ret = ppp_at_send_command("AT+CESQ", "OK", 5000, &response); + + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("AT+CESQ command failed: %d", ret); + return ret; + } + + // 解析响应 + ret = ppp_parse_cesq_response(response.response, info); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("Failed to parse CESQ response"); + return ret; + } + + // 打印详细信息 + PPP_DEBUG_INFO("=== Network Signal Information (AT+CESQ) ==="); + PPP_DEBUG_INFO("rxlev: %d", info->rxlev); + PPP_DEBUG_INFO("ber: %d", info->ber); + PPP_DEBUG_INFO("rscp: %d", info->rscp); + PPP_DEBUG_INFO("ecno: %d", info->ecno); + PPP_DEBUG_INFO("rsrq: %d", info->rsrq); + PPP_DEBUG_INFO("rsrp: %d", info->rsrp); + + // LTE信号质量评估 - 仅关注RSRQ和RSRP + PPP_DEBUG_INFO("=== LTE Signal Quality Analysis ==="); + + // RSRQ评估 (0-49有效,255无效) + if (info->rsrq == 255) { + PPP_DEBUG_INFO("RSRQ: 无法获取LTE信号质量"); + } else if (info->rsrq >= 0 && info->rsrq <= 49) { + // RSRQ转换公式: 实际值(dB) = (rsrq - 94)/10 + float rsrq_db = (info->rsrq - 94) / 10.0f; + PPP_DEBUG_INFO("RSRQ: %d (%.1f dB)", info->rsrq, rsrq_db); + + // RSRQ评估标准 (范围: -19.5dB ~ -3dB,数值越大质量越好) + if (rsrq_db >= -6.0) { + PPP_DEBUG_INFO("RSRQ评级: 极佳 (信号质量优秀)"); + } else if (rsrq_db >= -9.0) { + PPP_DEBUG_INFO("RSRQ评级: 良好 (信号质量稳定)"); + } else if (rsrq_db >= -12.0) { + PPP_DEBUG_INFO("RSRQ评级: 一般 (信号质量可用)"); + } else { + PPP_DEBUG_INFO("RSRQ评级: 较差 (信号质量不佳)"); + } + } else { + PPP_DEBUG_INFO("RSRQ: %d (超出有效范围0-49)", info->rsrq); + } + + // RSRP评估 (0-97有效,255无效) + if (info->rsrp == 255) { + PPP_DEBUG_INFO("RSRP: 无法获取LTE信号强度"); + } else if (info->rsrp >= 0 && info->rsrp <= 97) { + // RSRP转换公式: 实际值(dBm) = rsrp - 140 + float rsrp_dbm = info->rsrp - 140.0f; + PPP_DEBUG_INFO("RSRP: %d (%.0f dBm)", info->rsrp, rsrp_dbm); + + // RSRP评估标准 (范围: -140dBm ~ -43dBm,数值越大信号越强) + if (rsrp_dbm >= -80) { + PPP_DEBUG_INFO("RSRP评级: 极佳 (信号强度优秀)"); + } else if (rsrp_dbm >= -90) { + PPP_DEBUG_INFO("RSRP评级: 良好 (信号强度稳定)"); + } else if (rsrp_dbm >= -100) { + PPP_DEBUG_INFO("RSRP评级: 一般 (信号强度可用)"); + } else { + PPP_DEBUG_INFO("RSRP评级: 较差 (信号强度不足)"); + } + } else { + PPP_DEBUG_INFO("RSRP: %d (超出有效范围0-97)", info->rsrp); + } + + // 综合LTE信号质量评估 + if (info->rsrq != 255 && info->rsrp != 255 && + info->rsrq >= 0 && info->rsrq <= 49 && + info->rsrp >= 0 && info->rsrp <= 97) { + + float rsrq_db = (info->rsrq - 94) / 10.0f; + float rsrp_dbm = info->rsrp - 140.0f; + + const char *overall_quality = "未知"; + if (rsrq_db >= -6.0 && rsrp_dbm >= -80) { + overall_quality = "LTE信号极佳 (质量和强度都优秀)"; + } else if (rsrq_db >= -9.0 && rsrp_dbm >= -90) { + overall_quality = "LTE信号良好 (质量和强度都稳定)"; + } else if (rsrq_db >= -12.0 && rsrp_dbm >= -100) { + overall_quality = "LTE信号一般 (质量和强度可用)"; + } else { + overall_quality = "LTE信号较差 (需要改善网络环境)"; + } + + PPP_DEBUG_INFO("=== 综合评估: %s ===", overall_quality); + } else { + PPP_DEBUG_INFO("=== 综合评估: LTE参数无效,无法评估 ==="); + } + + PPP_DEBUG_INFO("=== End Network Signal Information ==="); + + return PPP_ERR_OK; +} \ No newline at end of file diff --git a/code/sdk/zhihui/ppp/src/ppp_lwip.c b/code/sdk/zhihui/ppp/src/ppp_lwip.c index c84e4e5f2..a734b8b31 100644 --- a/code/sdk/zhihui/ppp/src/ppp_lwip.c +++ b/code/sdk/zhihui/ppp/src/ppp_lwip.c @@ -178,20 +178,47 @@ void ppp_lwip_deinit(void) ppp_lwip_disconnect(); } + /* 清理网络接口 */ + if (g_lwip_ctx.netif) { + PPP_DEBUG_INFO("Cleaning up PPP network interface..."); + + /* 如果PPP接口是默认接口,清除默认接口设置 */ + if (netif_default == g_lwip_ctx.netif) { + PPP_DEBUG_INFO("Clearing PPP interface as default"); + netif_set_default(NULL); + } + + /* 设置接口为down状态 */ + if (netif_is_up(g_lwip_ctx.netif)) { + PPP_DEBUG_INFO("Setting PPP interface down"); + netif_set_down(g_lwip_ctx.netif); + } + + /* 设置链路为down状态 */ + if (netif_is_link_up(g_lwip_ctx.netif)) { + PPP_DEBUG_INFO("Setting PPP link down"); + netif_set_link_down(g_lwip_ctx.netif); + } + + /* 从lwIP网络接口列表中移除 */ + PPP_DEBUG_INFO("Removing PPP interface from lwIP interface list"); + netif_remove(g_lwip_ctx.netif); + + /* 释放网络接口内存 */ + PPP_DEBUG_INFO("Freeing PPP interface memory"); + osal_kfree(g_lwip_ctx.netif); + g_lwip_ctx.netif = NULL; + } + /* 删除PPP控制块 */ if (g_lwip_ctx.ppp_pcb) { + PPP_DEBUG_INFO("Freeing PPP control block"); ppp_free(g_lwip_ctx.ppp_pcb); g_lwip_ctx.ppp_pcb = NULL; } - /* 释放网络接口 */ - if (g_lwip_ctx.netif) { - osal_kfree(g_lwip_ctx.netif); - g_lwip_ctx.netif = NULL; - } - memset_s(&g_lwip_ctx, sizeof(g_lwip_ctx), 0, sizeof(g_lwip_ctx)); - PPP_DEBUG_INFO("PPP lwIP integration deinitialized"); + PPP_DEBUG_INFO("PPP lwIP integration deinitialized - network interface removed"); #endif } diff --git a/code/sdk/zhihui/ppp/src/ppp_power_ctl.c b/code/sdk/zhihui/ppp/src/ppp_power_ctl.c index a3719384e..3364e0b75 100644 --- a/code/sdk/zhihui/ppp/src/ppp_power_ctl.c +++ b/code/sdk/zhihui/ppp/src/ppp_power_ctl.c @@ -54,9 +54,9 @@ static ppp_ctl_pin_4g_t g_ppp_cat1_ctl_pins = { S_AGPIO_L23, // pwr_pin 1, S_AGPIO_L24,//reset_pin - 0, - PIN_NONE,//ring_pin - 0, + 1, //电路中 控制gpio拉高,reset才拉低 + S_MGPIO21,//ring_pin + 2, S_MGPIO22,//wakemodem_pin 1, #else @@ -109,14 +109,23 @@ void ppp_api_gpio_init(void) } gpiopin=g_ppp_cat1_ctl_pins.ring_pin; - if (gpiopin!=PIN_NONE) + if (gpiopin != PIN_NONE) { uapi_pin_set_mode(gpiopin, (pin_mode_t)HAL_PIO_FUNC_GPIO); - uapi_gpio_set_dir(gpiopin,GPIO_DIRECTION_INPUT); - if (g_ppp_cat1_ctl_pins.ring_pin_en_value) - uapi_gpio_register_isr_func(gpiopin, GPIO_INTERRUPT_RISING_EDGE, ppp_ring_isr_callback ); - else - uapi_gpio_register_isr_func(gpiopin, GPIO_INTERRUPT_FALLING_EDGE, ppp_ring_isr_callback ); + uapi_gpio_set_dir(gpiopin, GPIO_DIRECTION_INPUT); + switch (g_ppp_cat1_ctl_pins.ring_pin_en_value) + { + case 0: + uapi_gpio_register_isr_func(gpiopin, GPIO_INTERRUPT_FALLING_EDGE, ppp_ring_isr_callback); + break; + case 1: + uapi_gpio_register_isr_func(gpiopin, GPIO_INTERRUPT_RISING_EDGE, ppp_ring_isr_callback); + break; + case 2: + default: + uapi_gpio_register_isr_func(gpiopin, GPIO_INTERRUPT_DEDGE, ppp_ring_isr_callback); + break; + } } } @@ -169,25 +178,27 @@ uint32_t ppp_api_cat1_reset(uint32_t pwron) return 0xff; } - if (pwron == 0) { + if (pwron == 0) { //取消复位 uapi_gpio_set_dir(en_pin, GPIO_DIRECTION_OUTPUT); - if (en_value) { + if (en_value) { //拉高复位,取消复位,应拉低 uapi_gpio_set_val(en_pin, GPIO_LEVEL_LOW); PPP_DEBUG_PRINT("PPP: Cat1 reset Off! pin %d value low\n", en_pin); - } else { + } else { //拉低复位,取消复位,应拉高 uapi_gpio_set_val(en_pin, GPIO_LEVEL_HIGH); PPP_DEBUG_PRINT("PPP: Cat1 reset Off! pin %d value high\n", en_pin); } - } else { + } else { //复位 uapi_gpio_set_dir(en_pin, GPIO_DIRECTION_OUTPUT); - if (en_value) { + if (en_value) { //拉高复位 uapi_gpio_set_val(en_pin, GPIO_LEVEL_HIGH); PPP_DEBUG_PRINT("PPP: Cat1 reset On! pin %d value high\n", en_pin); - } else { + } else { //拉低复位 uapi_gpio_set_val(en_pin, GPIO_LEVEL_LOW); PPP_DEBUG_PRINT("PPP: Cat1 reset On! pin %d value low\n", en_pin); } } + uint8_t value = uapi_gpio_get_output_val(en_pin); + PPP_DEBUG_PRINT("PPP: Cat1 reset value %d\n", value); return 0; } @@ -261,7 +272,13 @@ void ppp_power_on_cat1(void) #if defined(BOARD_FD230) ppp_api_cat1_power_on(1); ppp_api_cat1_reset(0); -#elif (defined(BOARD_W9) || defined(BOARD_N9) || defined(BOARD_LEINIAO)) +#elif (defined(BOARD_W9) || defined(BOARD_N9) ) + ppp_api_cat1_power_on(1); + ppp_api_cat1_bat_on(1); + osal_msleep(900); // 使用OSAL延时函数 + ppp_api_cat1_power_on(0); +#elif defined(BOARD_LEINIAO) + ppp_api_cat1_reset(0); ppp_api_cat1_power_on(1); ppp_api_cat1_bat_on(1); osal_msleep(900); // 使用OSAL延时函数 @@ -280,7 +297,11 @@ void ppp_power_off_cat1(void) #if defined(BOARD_FD230) ppp_api_cat1_reset(1); ppp_api_cat1_power_on(0); -#elif (defined(BOARD_W9) || defined(BOARD_N9) || defined(BOARD_LEINIAO)) +#elif (defined(BOARD_W9) || defined(BOARD_N9) ) + ppp_api_cat1_power_on(0); + ppp_api_cat1_bat_on(0); +#elif defined(BOARD_LEINIAO) + ppp_api_cat1_reset(0); ppp_api_cat1_power_on(0); ppp_api_cat1_bat_on(0); #endif @@ -368,8 +389,16 @@ errcode_t ppp_register_ctl_pin(ppp_ctl_pin_4g_t *ctl_pin) void ppp_ring_isr_callback(pin_t pin, uintptr_t param) { (void)param; - PPP_DEBUG_PRINT("PPP: Cat1 ring interrupt on pin %d\n", pin); - // 中断处理逻辑 + + gpio_level_t val = uapi_gpio_get_val(pin); + if (val == GPIO_LEVEL_HIGH) { + PPP_DEBUG_PRINT("PPP: Cat1 ring interrupt on pin %d high \n", pin); + ppp_api_wakeup_cat1(true); + } else { + PPP_DEBUG_PRINT("PPP: Cat1 ring interrupt on pin %d low\n", pin); + ppp_api_wakeup_cat1(false); + } + uapi_gpio_clear_interrupt(pin); } /** diff --git a/code/sdk/zhihui/ppp/src/ppp_serial.c b/code/sdk/zhihui/ppp/src/ppp_serial.c index 17ff98b15..decb80fbc 100644 --- a/code/sdk/zhihui/ppp/src/ppp_serial.c +++ b/code/sdk/zhihui/ppp/src/ppp_serial.c @@ -357,6 +357,8 @@ ppp_error_t ppp_serial_write(const uint8_t *data, uint32_t length) } PPP_DEBUG_INFO("=== PPP Serial Write Start ==="); + ppp_api_wakeup_cat1(true); + osal_msleep(1); PPP_DEBUG_INFO("Write request: %u bytes in mode %d", length, g_serial_ctx.current_mode); PPP_DEBUG_INFO("UART Bus: %u", g_serial_ctx.uart_bus); @@ -428,6 +430,7 @@ ppp_error_t ppp_serial_write(const uint8_t *data, uint32_t length) result == PPP_ERR_OK ? "SUCCESS" : "FAILED", result); PPP_DEBUG_INFO("Statistics: tx_bytes=%u, tx_errors=%u", g_serial_ctx.tx_bytes, g_serial_ctx.tx_errors); PPP_DEBUG_INFO("=== PPP Serial Write End ==="); + ppp_api_wakeup_cat1(false); return result; } diff --git a/code/sdk/zhihui/ppp/src/ppp_stub_functions.c b/code/sdk/zhihui/ppp/src/ppp_stub_functions.c new file mode 100644 index 000000000..1f73edaac --- /dev/null +++ b/code/sdk/zhihui/ppp/src/ppp_stub_functions.c @@ -0,0 +1,90 @@ +/** + * @file ppp_stub_functions.c + * @brief 桩函数实现,用于解决编译链接时的未定义引用问题 + * + * 这些函数在PPP模块中不会被实际使用,仅用于满足链接器的符号依赖要求 + */ + +#include +#include +#include + +/** + * @brief HTTP客户端文件下载桩函数 + * @param url 下载URL + * @param file_path 本地文件路径 + * @param timeout 超时时间 + * @return 总是返回失败(-1) + */ +int httpc_get_file_dns_to_disk(const char *url, const char *file_path, int timeout) +{ + (void)url; + (void)file_path; + (void)timeout; + + // 桩函数 - 不实现实际功能 + return -1; +} + +/** + * @brief AI流式录音发送桩函数 + * @param data 音频数据 + * @param len 数据长度 + * @param session_id 会话ID + * @return 总是返回失败(-1) + */ +int streamingRecordAndSend_AI(void *data, int len, const char *session_id) +{ + (void)data; + (void)len; + (void)session_id; + + // 桩函数 - 不实现实际功能 + return -1; +} + +/** + * @brief AI消息队列发送桩函数 + * @param msg_data 消息数据 + * @param data_len 数据长度 + * @return 总是返回失败(-1) + */ +int send_msg_data_into_Ai_msg_queue(void *msg_data, int data_len) +{ + (void)msg_data; + (void)data_len; + + // 桩函数 - 不实现实际功能 + return -1; +} + +/** + * @brief 蓝牙设置AI回答字符串桩函数 + * @param answer_str AI回答字符串 + * @return 总是返回失败(-1) + */ +int ble_set_ai_Answer_str(const char *answer_str) +{ + (void)answer_str; + + // 桩函数 - 不实现实际功能 + return -1; +} + +/** + * @brief 蓝牙设置AI问题字符串桩函数 + * @param question_str AI问题字符串 + * @return 总是返回失败(-1) + */ +int ble_set_ai_Question_str(const char *question_str) +{ + (void)question_str; + + // 桩函数 - 不实现实际功能 + return -1; +} + +/* + * 注意:这些桩函数仅用于解决链接问题,不提供实际功能 + * 如果需要使用相关功能,请实现对应的真实函数 + */ \ No newline at end of file diff --git a/code/sdk/zhihui/utils/custom_utils.c b/code/sdk/zhihui/utils/custom_utils.c index 2bd48c791..96d3d4b8e 100644 --- a/code/sdk/zhihui/utils/custom_utils.c +++ b/code/sdk/zhihui/utils/custom_utils.c @@ -636,6 +636,10 @@ void startup_post_init_task(void) #ifdef CUSTOM_ZHIHUI system_init_uart();//配置uartat #endif + +#ifdef BOARD_LEINIAO + // zhihui_ppp_init(); +#else if ( cm_poweron_cat1_on_bootup_flag() ) { PRINT("PowerOn Cat1 !\r\n"); @@ -644,6 +648,7 @@ void startup_post_init_task(void) PRINT("PowerOff Cat1 !\r\n"); uapi_set4GCapability(false); } +#endif uapi_gei_btmac_and_chipinfo(); uint8_t buildversion[128]={0}; -- 2.17.1