From: 孙春阳 Date: Thu, 11 Sep 2025 08:43:21 +0000 (+0800) Subject: 更新ppp 实现 X-Git-Tag: leiniao_debug_1.0.0_20250922_020716~92^2~6 X-Git-Url: http://git.snicker.com.cn/css/static/gitweb.css?a=commitdiff_plain;h=942fdc70b2ed6766e49a4b5e823b7cfaa2d02f27;p=mirrors%2FFD230.git 更新ppp 实现 --- diff --git a/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/arch/sio.c b/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/arch/sio.c index fae1e8989..550595083 100644 --- a/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/arch/sio.c +++ b/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/arch/sio.c @@ -76,7 +76,7 @@ static bool g_sio_uart_initialized = false; static uint8_t g_sio_write_buffer[SIO_WRITE_BUFFER_SIZE]; static uint32_t g_sio_write_buffer_pos = 0; -extern void uart_slip_read_int_handler(const void *buffer, uint16_t length, bool error); +extern void uart_read_data_int_handler(const void *buffer, uint16_t length, bool error); /** * Initialize SIO UART @@ -98,7 +98,7 @@ static errcode_t sio_uart_init(void) } ret = uapi_uart_register_rx_callback(SIO_UART_BUS, UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE, - SIO_UART_RX_BUFFER_SIZE, uart_slip_read_int_handler); + SIO_UART_RX_BUFFER_SIZE, uart_read_data_int_handler); printf("uapi_uart_register_rx_callback ret=%x\r\n", ret); diff --git a/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/test/slip_test.c b/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/test/slip_test.c index 6a7ade699..31432c228 100644 --- a/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/test/slip_test.c +++ b/code/sdk/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/test/slip_test.c @@ -100,7 +100,7 @@ void slip_test_send(void) } } -void uart_slip_read_int_handler(const void *buffer, uint16_t length, bool error) +void uart_read_data_int_handler(const void *buffer, uint16_t length, bool error) { if (slipif_initialled == true) { diff --git a/code/sdk/zhihui/ppp/CMakeLists.txt b/code/sdk/zhihui/ppp/CMakeLists.txt index eedeb85e7..996c72a07 100644 --- a/code/sdk/zhihui/ppp/CMakeLists.txt +++ b/code/sdk/zhihui/ppp/CMakeLists.txt @@ -68,6 +68,7 @@ set(PUBLIC_DEFINES PRINTPKT_SUPPORT=1 PPP_DEBUG=LWIP_DBG_ON PPP_INPROC_IRQ_SAFE=0 + PPP_OPTIONS=1 SUPPORT_PPP_SERVICE SUPPORT_AT_PPP ) diff --git a/code/sdk/zhihui/ppp/example/ppp_example.c b/code/sdk/zhihui/ppp/example/ppp_example.c index aa0cd09ad..f1b826492 100644 --- a/code/sdk/zhihui/ppp/example/ppp_example.c +++ b/code/sdk/zhihui/ppp/example/ppp_example.c @@ -26,16 +26,22 @@ int ppp_example_main(void) /* 配置PPP拨号参数 */ ppp_config_t config = { - .apn = "cmnet", // 中国移动APN + .apn = "cmnet", // 中国移动APN (对应AT+CGDCONT中的APN) .username = "", // 用户名(通常为空) .password = "", // 密码(通常为空) - .baudrate = 2000000, // 2M波特率 - .auto_baudrate = true, // 启用自动波特率检测 - .dial_timeout = 30000, // 30秒拨号超时 + .baudrate = 2000000, // 2M波特率 (对应AT+IPR=2000000) + .auto_baudrate = true, // 启用自动波特率检测 (对应chat文件中的AT握手) + .dial_timeout = 30000, // 30秒拨号超时 (对应chat文件TIMEOUT 5) .retry_count = 3 // 重试3次 }; /* 初始化PPP拨号系统 */ + /* 这将执行完整的chat文件流程: + * 1. 跳过开机日志 (对应 '' \rAT) + * 2. AT握手 (对应 AT -> OK) + * 3. 设置PDP上下文 (对应 AT+CGDCONT=3,"IP") + * 4. PPP拨号 (对应 ATD*99***2# -> CONNECTED) + */ errcode_t ret = zhihui_ppp_init(&config); if (ret != ERRCODE_SUCC) { diff --git a/code/sdk/zhihui/ppp/include/ppp_api.h b/code/sdk/zhihui/ppp/include/ppp_api.h index 92ec12cd8..8c02107fe 100644 --- a/code/sdk/zhihui/ppp/include/ppp_api.h +++ b/code/sdk/zhihui/ppp/include/ppp_api.h @@ -35,6 +35,18 @@ errcode_t ppp_start_dial(void); */ errcode_t ppp_stop_dial(void); +/** + * @brief 启动PPP数据接收线程 + * @return 错误码 + */ +ppp_error_t ppp_start_data_receive_thread(void); + +/** + * @brief 停止PPP数据接收线程 + * @return 错误码 + */ +ppp_error_t ppp_stop_data_receive_thread(void); + /** * @brief 获取PPP连接状态 * @return PPP状态 diff --git a/code/sdk/zhihui/ppp/include/ppp_at_handler.h b/code/sdk/zhihui/ppp/include/ppp_at_handler.h index 50f934169..a11586dd1 100644 --- a/code/sdk/zhihui/ppp/include/ppp_at_handler.h +++ b/code/sdk/zhihui/ppp/include/ppp_at_handler.h @@ -52,6 +52,13 @@ ppp_error_t ppp_at_set_baudrate(uint32_t baudrate); */ ppp_error_t ppp_at_auto_detect_baudrate(void); +/** + * @brief 完整的PPP拨号序列 (对应chat文件的完整流程) + * @param apn APN接入点名称 + * @return 错误码 + */ +ppp_error_t ppp_at_complete_dial_sequence(const char *apn); + #ifdef __cplusplus } #endif diff --git a/code/sdk/zhihui/ppp/include/ppp_config.h b/code/sdk/zhihui/ppp/include/ppp_config.h index b9dce078e..01499707a 100644 --- a/code/sdk/zhihui/ppp/include/ppp_config.h +++ b/code/sdk/zhihui/ppp/include/ppp_config.h @@ -10,6 +10,20 @@ extern "C" { /* PPP配置参数 - UART配置统一使用SIO (在lwipopts_default.h中定义) */ +/* SIO设备号配置 - 与SLIP区分开 */ +#define PPP_IFNUM 1 // PPP使用的SIO设备号,与SLIP_IFNUM(0)区分 + +/* UART引脚配置 - 对应SIO配置 */ +#ifndef SIO_UART_TX_PIN +#define SIO_UART_TX_PIN S_AGPIO_L25 // UART TX引脚 +#endif +#ifndef SIO_UART_RX_PIN +#define SIO_UART_RX_PIN S_AGPIO_L26 // UART RX引脚 +#endif +#ifndef SIO_UART_BUS +#define SIO_UART_BUS UART_BUS_1 // UART总线 +#endif + /* 支持的波特率列表(自适应模式) */ #define PPP_BAUDRATE_AUTO_LIST {9600, 57600, 115200} #define PPP_BAUDRATE_AUTO_COUNT 3 @@ -31,7 +45,10 @@ extern "C" { /* 缓冲区大小配置 */ #define PPP_RX_BUFFER_SIZE 2048 // 接收缓冲区大小 -#define PPP_TX_BUFFER_SIZE 1024 // 发送缓冲区大小 +#define PPP_TX_BUFFER_SIZE 2048 // 发送缓冲区大小 + +/* PPP数据接收线程配置 */ +#define PPP_RX_THREAD_STACK_SIZE 4096 // PPP数据接收线程栈大小 /* PPP网络配置 */ #define PPP_MTU_SIZE 1500 // PPP MTU大小 diff --git a/code/sdk/zhihui/ppp/include/ppp_power_ctl.h b/code/sdk/zhihui/ppp/include/ppp_power_ctl.h index c1851fb9f..487bf0b82 100644 --- a/code/sdk/zhihui/ppp/include/ppp_power_ctl.h +++ b/code/sdk/zhihui/ppp/include/ppp_power_ctl.h @@ -122,6 +122,11 @@ void ppp_ring_isr_callback(pin_t pin, uintptr_t param); */ void ppp_api_enable_cat1(bool isopen); +/** + * @brief PPP模块反初始化 + */ +void ppp_api_deinit(void); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/code/sdk/zhihui/ppp/include/ppp_serial.h b/code/sdk/zhihui/ppp/include/ppp_serial.h index 1a2c33470..75655c296 100644 --- a/code/sdk/zhihui/ppp/include/ppp_serial.h +++ b/code/sdk/zhihui/ppp/include/ppp_serial.h @@ -94,6 +94,13 @@ ppp_error_t ppp_serial_set_baudrate(uint32_t baudrate); */ void ppp_serial_get_stats(ppp_serial_stats_t *stats); +/** + * @brief 获取PPP模块SIO句柄 + * @return SIO句柄,如果未初始化则返回NULL + */ +#include "lwip/sio.h" +sio_fd_t ppp_get_sio_fd(void); + #ifdef __cplusplus } #endif diff --git a/code/sdk/zhihui/ppp/src/ppp_api.c b/code/sdk/zhihui/ppp/src/ppp_api.c index c6df73cb9..8ccff1ca3 100644 --- a/code/sdk/zhihui/ppp/src/ppp_api.c +++ b/code/sdk/zhihui/ppp/src/ppp_api.c @@ -1,6 +1,8 @@ #include "ppp_api.h" #include "ppp_debug.h" #include "ppp_power_ctl.h" +#include "ppp_at_handler.h" // 添加AT处理头文件 +#include "ppp_serial.h" // 添加串口处理头文件 #include "osal_debug.h" #include "schedule/osal_task.h" #include "securec.h" @@ -58,14 +60,83 @@ errcode_t ppp_start_dial(void) // 2. 等待4G模块启动 osal_msleep(2000); - // 3. 初始化AT命令处理 - // TODO: 实现AT命令初始化 + // 3. 初始化AT命令处理(AT命令模式) + ppp_error_t ret = ppp_at_handler_init(SIO_UART_BUS); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_PRINT("Failed to initialize AT handler: %d\n", ret); + return ERRCODE_FAIL; + } - // 4. 启动PPP协议栈 - // TODO: 实现PPP协议栈启动 + // 4. 执行波特率握手(如果启用自动波特率) + 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); + return ERRCODE_FAIL; + } + } - g_ppp_state = PPP_STATE_DIALING; - PPP_DEBUG_PRINT("PPP dial started\n"); + // 5. 执行完整的AT指令序列(对应chat文件) + ret = ppp_at_complete_dial_sequence(g_ppp_config.apn); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_PRINT("PPP dial sequence failed: %d\n", ret); + g_ppp_state = PPP_STATE_ERROR; + return ERRCODE_FAIL; + } + + PPP_DEBUG_PRINT("AT dial sequence completed - switching to PPP data mode\n"); + + // 6. 关闭AT命令处理器(释放UART资源) + ppp_at_handler_deinit(); + PPP_DEBUG_PRINT("AT handler deinitialized - UART released\n"); + + // 7. 初始化SIO串口(PPP数据模式) + ppp_serial_config_t serial_config = { + .uart_bus = SIO_UART_BUS, + .baudrate = g_ppp_config.baudrate, + .tx_pin = SIO_UART_TX_PIN, + .rx_pin = SIO_UART_RX_PIN, + .rx_buffer_size = PPP_RX_BUFFER_SIZE, + .tx_buffer_size = PPP_TX_BUFFER_SIZE, + .rx_callback = NULL, // 将在PPP数据接收线程中设置 + .rx_callback_arg = NULL + }; + + ret = ppp_serial_init(&serial_config); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_PRINT("Failed to initialize serial for PPP data mode: %d\n", ret); + return ERRCODE_FAIL; + } + + // 8. 初始化lwIP PPP协议栈 + ret = ppp_lwip_init(); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_PRINT("Failed to initialize lwIP PPP: %d\n", ret); + ppp_serial_deinit(); + return ERRCODE_FAIL; + } + + // 9. 启动PPP连接 + ret = ppp_lwip_connect(); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_PRINT("Failed to start PPP connection: %d\n", ret); + ppp_lwip_deinit(); + ppp_serial_deinit(); + return ERRCODE_FAIL; + } + + // 10. 启动PPP数据接收处理 + ret = ppp_start_data_receive_thread(); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_PRINT("Failed to start PPP data receive thread: %d\n", ret); + ppp_lwip_disconnect(); + ppp_lwip_deinit(); + ppp_serial_deinit(); + return ERRCODE_FAIL; + } + + g_ppp_state = PPP_STATE_CONNECTED; + PPP_DEBUG_PRINT("PPP dial completed successfully - now in data mode\n"); return ERRCODE_SUCC; } @@ -77,14 +148,47 @@ errcode_t ppp_stop_dial(void) { PPP_DEBUG_PRINT("Stopping PPP connection\n"); - // 1. 停止PPP协议栈 - // TODO: 实现PPP协议栈停止 + if (g_ppp_state != PPP_STATE_CONNECTED) { + PPP_DEBUG_WARN("PPP not connected, current state: %d", g_ppp_state); + return ERRCODE_SUCC; + } + + // 1. 停止PPP数据接收线程 + ppp_stop_data_receive_thread(); + + // 2. 断开lwIP PPP连接 + ppp_lwip_disconnect(); + + // 3. 清理lwIP PPP资源 + ppp_lwip_deinit(); + + // 4. 关闭SIO串口(释放串口资源) + ppp_serial_deinit(); + PPP_DEBUG_PRINT("SIO serial deinitialized - switching back to AT mode\n"); + + // 5. 重新初始化AT命令处理器(切换回AT命令模式) + ppp_error_t ret = ppp_at_handler_init(SIO_UART_BUS); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("Failed to reinitialize AT handler: %d", ret); + g_ppp_state = PPP_STATE_ERROR; + return ERRCODE_FAIL; + } + + // 6. 发送PPP挂断命令(切换回命令模式) + ret = ppp_at_hangup_ppp(); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_WARN("Failed to send hangup command: %d", ret); + // 继续执行,不返回错误 + } + + // 7. 关闭AT命令处理器 + ppp_at_handler_deinit(); - // 2. 关闭4G电源(通过兼容接口) + // 8. 关闭4G电源 cat1_api_enable_cat1(false); - g_ppp_state = PPP_STATE_IDLE; - PPP_DEBUG_PRINT("PPP connection stopped\n"); + g_ppp_state = PPP_STATE_INITIALIZED; + PPP_DEBUG_PRINT("PPP connection stopped successfully\n"); return ERRCODE_SUCC; } @@ -148,4 +252,85 @@ errcode_t zhihui_ppp_deinit(void) PPP_DEBUG_PRINT("PPP module deinitialized\n"); return ERRCODE_SUCC; +} + +/* PPP数据接收线程相关 */ +static osal_task *g_ppp_rx_task = NULL; +static bool g_ppp_rx_thread_running = false; + +/** + * @brief PPP数据接收线程 + */ +static void ppp_data_receive_thread(void *arg) +{ + (void)arg; + + PPP_DEBUG_PRINT("PPP data receive thread started\n"); + + uint8_t rx_buffer[PPP_RX_BUFFER_SIZE]; + uint32_t bytes_read; + + while (g_ppp_rx_thread_running) { + // 从串口读取PPP数据 + ppp_error_t ret = ppp_serial_read(rx_buffer, sizeof(rx_buffer), &bytes_read); + if (ret == PPP_ERR_OK && bytes_read > 0) { + // 将数据传递给lwIP PPP协议栈 + ppp_lwip_input(rx_buffer, bytes_read); + } + + // 短暂延时,避免占用过多CPU + osal_msleep(1); + } + + PPP_DEBUG_PRINT("PPP data receive thread stopped\n"); +} + +/** + * @brief 启动PPP数据接收线程 + */ +ppp_error_t ppp_start_data_receive_thread(void) +{ + if (g_ppp_rx_task != NULL) { + PPP_DEBUG_WARN("PPP data receive thread already running"); + return PPP_ERR_OK; + } + + g_ppp_rx_thread_running = true; + + // 创建PPP数据接收线程 + g_ppp_rx_task = osal_kthread_create((osal_kthread_handler)ppp_data_receive_thread, + NULL, "ppp_rx_thread", PPP_RX_THREAD_STACK_SIZE); + if (g_ppp_rx_task == NULL) { + PPP_DEBUG_ERROR("Failed to create PPP data receive thread"); + g_ppp_rx_thread_running = false; + return PPP_ERR_MEMORY; + } + + PPP_DEBUG_INFO("PPP data receive thread created successfully"); + return PPP_ERR_OK; +} + +/** + * @brief 停止PPP数据接收线程 + */ +ppp_error_t ppp_stop_data_receive_thread(void) +{ + if (g_ppp_rx_task == NULL) { + return PPP_ERR_OK; + } + + PPP_DEBUG_INFO("Stopping PPP data receive thread"); + + // 停止线程 + g_ppp_rx_thread_running = false; + + // 等待线程结束 + osal_msleep(100); + + // 销毁线程 + osal_kthread_destroy(g_ppp_rx_task, 0); + g_ppp_rx_task = NULL; + + PPP_DEBUG_INFO("PPP data receive thread stopped"); + return PPP_ERR_OK; } \ 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 827fde92a..970af1938 100644 --- a/code/sdk/zhihui/ppp/src/ppp_at_handler.c +++ b/code/sdk/zhihui/ppp/src/ppp_at_handler.c @@ -237,6 +237,94 @@ ppp_error_t ppp_at_send_command(const char *command, const char *expected_respon return ret; } +/** + * @brief 跳过开机日志 (对应chat文件中的 '' \rAT) + */ +static ppp_error_t ppp_at_skip_startup_logs(void) +{ + PPP_DEBUG_INFO("Skipping startup logs..."); + + // 清空接收缓冲区,跳过开机时的各种日志输出 + uint8_t dummy_buffer[256]; + uint32_t bytes_read; + + // 连续读取并丢弃开机日志,直到没有更多数据 + int retry_count = 0; + const int max_retries = 10; + + do { + ppp_error_t ret = ppp_serial_read(dummy_buffer, sizeof(dummy_buffer), &bytes_read); + if (ret != PPP_ERR_OK) { + break; + } + + if (bytes_read > 0) { + PPP_DEBUG_DEBUG("Skipped %u bytes of startup logs", bytes_read); + retry_count = 0; // 重置重试计数 + } else { + retry_count++; + } + + osal_msleep(100); + } while (retry_count < max_retries); + + PPP_DEBUG_INFO("Startup logs skipped"); + return PPP_ERR_OK; +} + +/** + * @brief 完整的PPP拨号序列 (对应chat文件的完整流程) + */ +ppp_error_t ppp_at_complete_dial_sequence(const char *apn) +{ + ppp_at_response_t response; + ppp_error_t ret; + + PPP_DEBUG_INFO("Starting complete PPP dial sequence"); + + // 1. 跳过开机日志 (对应chat文件: '' \rAT) + ret = ppp_at_skip_startup_logs(); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("Failed to skip startup logs"); + return ret; + } + + // 2. 发送AT测试连接 (对应chat文件: '' \rAT -> OK) + ret = ppp_at_send_command("AT", "OK", 5000, &response); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("AT handshake failed"); + return ret; + } + PPP_DEBUG_INFO("AT handshake successful"); + + // 3. 设置PDP上下文 (对应chat文件: OK 'AT+CGDCONT=3,"IP"') + char cgdcont_cmd[128]; + if (apn && strlen(apn) > 0) { + snprintf_s(cgdcont_cmd, sizeof(cgdcont_cmd), sizeof(cgdcont_cmd) - 1, + "AT+CGDCONT=3,\"IP\",\"%s\"", apn); + } else { + snprintf_s(cgdcont_cmd, sizeof(cgdcont_cmd), sizeof(cgdcont_cmd) - 1, + "AT+CGDCONT=3,\"IP\""); + } + + ret = ppp_at_send_command(cgdcont_cmd, "OK", 5000, &response); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("Failed to set PDP context: %s", cgdcont_cmd); + return ret; + } + PPP_DEBUG_INFO("PDP context set successfully"); + + // 4. 发送PPP拨号指令 (对应chat文件: OK 'ATD*99***2#' -> CONNECTED) + ret = ppp_at_send_command("ATD*99***2#", "CONNECT", 30000, &response); + if (ret != PPP_ERR_OK) { + PPP_DEBUG_ERROR("PPP dial failed"); + return ret; + } + + PPP_DEBUG_INFO("PPP dial sequence completed successfully - entering data mode"); + return PPP_ERR_OK; +} + /** * @brief 发送PPP拨号命令 */ @@ -319,11 +407,24 @@ bool ppp_at_is_auto_baudrate_mode(void) */ static bool ppp_at_parse_response(const char *response, const char *expected) { - if (!response || !expected) { + if (!response) { + return false; + } + + // 检查ABORT条件 (对应chat文件中的ABORT指令) + if (strstr(response, "BUSY") || + strstr(response, "ERROR") || + strstr(response, "NO CARRIER")) { + PPP_DEBUG_ERROR("AT command aborted: %s", response); return false; } - return strstr(response, expected) != NULL; + // 检查期望响应 + if (expected && strstr(response, expected)) { + return true; + } + + return false; } /** diff --git a/code/sdk/zhihui/ppp/src/ppp_lwip.c b/code/sdk/zhihui/ppp/src/ppp_lwip.c index c513de16b..845c056fb 100644 --- a/code/sdk/zhihui/ppp/src/ppp_lwip.c +++ b/code/sdk/zhihui/ppp/src/ppp_lwip.c @@ -3,6 +3,7 @@ #include "ppp_types.h" #include "ppp_debug.h" #include "ppp_serial.h" +#include "ppp_power_ctl.h" // 添加电源控制头文件 #include "securec.h" #include @@ -14,6 +15,7 @@ #include "lwip/dns.h" #include "netif/ppp/ppp.h" #include "netif/ppp/pppos.h" +#include "lwip/sio.h" // 添加SIO头文件 #endif /* PPP lwIP上下文 */ @@ -367,7 +369,7 @@ static void ppp_lwip_link_status_callback(ppp_pcb *pcb, int err_code, void *ctx) } /** - * @brief PPP输出回调函数 + * @brief PPP输出回调函数 - 使用SIO接口,像SLIP一样 */ static u32_t ppp_lwip_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) { @@ -377,13 +379,19 @@ static u32_t ppp_lwip_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void PPP_DEBUG_DEBUG("PPP output %u bytes", len); PPP_DEBUG_HEXDUMP(data, len); - /* 通过串口发送数据 */ - ppp_error_t ret = ppp_serial_write(data, len); - if (ret != PPP_ERR_OK) { - PPP_DEBUG_ERROR("Failed to send PPP data: %d", ret); + /* 通过SIO接口发送数据,像SLIP一样 */ + sio_fd_t sio_fd = ppp_get_sio_fd(); + if (sio_fd == NULL) { + PPP_DEBUG_ERROR("SIO interface not initialized"); return 0; } - return len; + u32_t sent = sio_write(sio_fd, data, len); + if (sent != len) { + PPP_DEBUG_ERROR("Failed to send PPP data via SIO: %u/%u", sent, len); + return 0; + } + + return sent; } #endif /* LWIP_PPP_SUPPORT */ \ No newline at end of file diff --git a/code/sdk/zhihui/ppp/src/ppp_power_ctl.c b/code/sdk/zhihui/ppp/src/ppp_power_ctl.c index 923a524d5..e55342039 100644 --- a/code/sdk/zhihui/ppp/src/ppp_power_ctl.c +++ b/code/sdk/zhihui/ppp/src/ppp_power_ctl.c @@ -125,8 +125,8 @@ void ppp_api_gpio_init(void) */ void ppp_api_uart_init(void) { - PPP_DEBUG_PRINT("PPP UART init\n"); - // UART初始化逻辑可以在这里添加 + PPP_DEBUG_PRINT("PPP UART init - delegated to ppp_serial module\n"); + // UART初始化逻辑已移至ppp_serial.c中 } /** @@ -411,4 +411,17 @@ void ppp_api_enable_cat1(bool isopen) // 可以在这里添加PPP特定的清理逻辑 // 例如:停止PPP协议栈等 } +} + +/** + * @brief PPP模块反初始化 + */ +void ppp_api_deinit(void) +{ + PPP_DEBUG_PRINT("PPP: deinit\n"); + + // 关闭电源 + ppp_api_cat1_power_on(0); + + g_ppp_cat1_power_status = false; } \ No newline at end of file diff --git a/code/sdk/zhihui/ppp/src/ppp_serial.c b/code/sdk/zhihui/ppp/src/ppp_serial.c index bedea5f95..449a74e09 100644 --- a/code/sdk/zhihui/ppp/src/ppp_serial.c +++ b/code/sdk/zhihui/ppp/src/ppp_serial.c @@ -11,6 +11,10 @@ #include "securec.h" #include +// 添加SIO相关头文件,让PPP像SLIP一样使用SIO接口 +#include "lwip/sio.h" +#include "lwip/opt.h" + /* 串口上下文结构 */ typedef struct { bool initialized; @@ -19,6 +23,9 @@ typedef struct { uart_attr_t uart_attr; uart_buffer_config_t buffer_config; + /* SIO接口句柄 */ + sio_fd_t sio_fd; + /* 接收缓冲区 */ uint8_t *rx_buffer; uint32_t rx_buffer_size; @@ -61,103 +68,22 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config) return PPP_ERR_INVALID_PARAM; } - PPP_DEBUG_INFO("Initializing PPP serial on UART%d", config->uart_bus); - - /* 分配接收缓冲区 */ - g_serial_ctx.rx_buffer = (uint8_t *)osal_kmalloc(config->rx_buffer_size, OSAL_GFP_KERNEL); - if (!g_serial_ctx.rx_buffer) { - PPP_DEBUG_ERROR("Failed to allocate RX buffer"); - return PPP_ERR_MEMORY; - } - - /* 分配发送缓冲区 */ - g_serial_ctx.tx_buffer = (uint8_t *)osal_kmalloc(config->tx_buffer_size, OSAL_GFP_KERNEL); - if (!g_serial_ctx.tx_buffer) { - PPP_DEBUG_ERROR("Failed to allocate TX buffer"); - osal_kfree(g_serial_ctx.rx_buffer); - return PPP_ERR_MEMORY; - } + PPP_DEBUG_INFO("Initializing PPP serial using SIO interface like SLIP"); - /* 创建互斥锁 */ - if (osal_mutex_init(&g_serial_ctx.rx_mutex) != OSAL_SUCCESS) { - PPP_DEBUG_ERROR("Failed to create RX mutex"); - osal_kfree(g_serial_ctx.rx_buffer); - osal_kfree(g_serial_ctx.tx_buffer); - return PPP_ERR_MEMORY; - } - - /* 创建信号量 */ - if (osal_sem_init(&g_serial_ctx.rx_semaphore, 0) != OSAL_SUCCESS) { - PPP_DEBUG_ERROR("Failed to create RX semaphore"); - osal_mutex_destroy(g_serial_ctx.rx_mutex); - osal_kfree(g_serial_ctx.rx_buffer); - osal_kfree(g_serial_ctx.tx_buffer); - return PPP_ERR_MEMORY; + /* 打开SIO接口,使用与SLIP相同的方式但不同的设备号 */ + g_serial_ctx.sio_fd = sio_open(PPP_IFNUM); + if (g_serial_ctx.sio_fd == NULL) { + PPP_DEBUG_ERROR("Failed to open SIO interface for PPP, device=%d", PPP_IFNUM); + return PPP_ERR_UART; } - /* 配置串口参数 */ + /* 配置基本参数 */ g_serial_ctx.uart_bus = config->uart_bus; g_serial_ctx.rx_buffer_size = config->rx_buffer_size; g_serial_ctx.tx_buffer_size = config->tx_buffer_size; g_serial_ctx.rx_callback = config->rx_callback; g_serial_ctx.rx_callback_arg = config->rx_callback_arg; - /* 配置串口引脚 */ - g_serial_ctx.pin_config.tx_pin = config->tx_pin; - g_serial_ctx.pin_config.rx_pin = config->rx_pin; - g_serial_ctx.pin_config.cts_pin = PIN_NONE; - g_serial_ctx.pin_config.rts_pin = PIN_NONE; - - /* 配置串口属性 */ - g_serial_ctx.uart_attr.baud_rate = config->baudrate; - g_serial_ctx.uart_attr.data_bits = UART_DATA_BIT_8; - g_serial_ctx.uart_attr.parity = UART_PARITY_NONE; - g_serial_ctx.uart_attr.stop_bits = UART_STOP_BIT_1; - - /* 配置串口缓冲区 */ - g_serial_ctx.buffer_config.rx_buffer_size = 256; // 硬件缓冲区 - g_serial_ctx.buffer_config.rx_buffer = (uint8_t *)osal_kmalloc(256, OSAL_GFP_KERNEL); - if (!g_serial_ctx.buffer_config.rx_buffer) { - PPP_DEBUG_ERROR("Failed to allocate UART RX buffer"); - osal_sem_destroy(g_serial_ctx.rx_semaphore); - osal_mutex_destroy(g_serial_ctx.rx_mutex); - osal_kfree(g_serial_ctx.rx_buffer); - osal_kfree(g_serial_ctx.tx_buffer); - return PPP_ERR_MEMORY; - } - - /* 初始化串口 */ - 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); - if (ret != ERRCODE_SUCC) { - PPP_DEBUG_ERROR("Failed to initialize UART: %d", ret); - osal_kfree(g_serial_ctx.buffer_config.rx_buffer); - osal_sem_destroy(g_serial_ctx.rx_semaphore); - osal_mutex_destroy(g_serial_ctx.rx_mutex); - osal_kfree(g_serial_ctx.rx_buffer); - osal_kfree(g_serial_ctx.tx_buffer); - return PPP_ERR_UART; - } - - /* 注册接收回调 */ - ret = uapi_uart_register_rx_callback(g_serial_ctx.uart_bus, - UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE, - 1, // 接收到1个字节就触发回调 - ppp_serial_rx_callback); - if (ret != ERRCODE_SUCC) { - PPP_DEBUG_ERROR("Failed to register UART RX callback: %d", ret); - uapi_uart_deinit(g_serial_ctx.uart_bus); - osal_kfree(g_serial_ctx.buffer_config.rx_buffer); - osal_sem_destroy(g_serial_ctx.rx_semaphore); - osal_mutex_destroy(g_serial_ctx.rx_mutex); - osal_kfree(g_serial_ctx.rx_buffer); - osal_kfree(g_serial_ctx.tx_buffer); - return PPP_ERR_UART; - } - /* 初始化缓冲区状态 */ g_serial_ctx.rx_head = 0; g_serial_ctx.rx_tail = 0; @@ -174,7 +100,10 @@ ppp_error_t ppp_serial_init(const ppp_serial_config_t *config) return PPP_ERR_OK; } - +void uart_read_data_int_handler(const void *buffer, uint16_t length, bool error) +{ + ppp_serial_rx_callback(buffer, length,error); +} /** * @brief 反初始化PPP串口 */ @@ -186,28 +115,10 @@ void ppp_serial_deinit(void) PPP_DEBUG_INFO("Deinitializing PPP serial"); - /* 反初始化串口 */ - uapi_uart_deinit(g_serial_ctx.uart_bus); - - /* 释放资源 */ - if (g_serial_ctx.buffer_config.rx_buffer) { - osal_kfree(g_serial_ctx.buffer_config.rx_buffer); - } - - if (g_serial_ctx.rx_semaphore) { - osal_sem_destroy(g_serial_ctx.rx_semaphore); - } - - if (g_serial_ctx.rx_mutex) { - osal_mutex_destroy(g_serial_ctx.rx_mutex); - } - - if (g_serial_ctx.rx_buffer) { - osal_kfree(g_serial_ctx.rx_buffer); - } - - if (g_serial_ctx.tx_buffer) { - osal_kfree(g_serial_ctx.tx_buffer); + /* 关闭SIO接口 */ + if (g_serial_ctx.sio_fd != NULL) { + sio_close(g_serial_ctx.sio_fd); + g_serial_ctx.sio_fd = NULL; } memset_s(&g_serial_ctx, sizeof(g_serial_ctx), 0, sizeof(g_serial_ctx)); @@ -223,34 +134,25 @@ ppp_error_t ppp_serial_write(const uint8_t *data, uint32_t length) return PPP_ERR_INVALID_PARAM; } - if (length > g_serial_ctx.tx_buffer_size) { - PPP_DEBUG_ERROR("Data length exceeds TX buffer size"); - return PPP_ERR_INVALID_PARAM; + if (g_serial_ctx.sio_fd == NULL) { + PPP_DEBUG_ERROR("SIO interface not initialized"); + return PPP_ERR_UART; } - PPP_DEBUG_DEBUG("Sending %u bytes", length); + PPP_DEBUG_DEBUG("Sending %u bytes via SIO", length); PPP_DEBUG_HEXDUMP(data, length); - /* 复制数据到发送缓冲区 */ - memcpy_s(g_serial_ctx.tx_buffer, g_serial_ctx.tx_buffer_size, data, length); - - /* 发送数据 */ - int32_t bytes_written = uapi_uart_write(g_serial_ctx.uart_bus, g_serial_ctx.tx_buffer, length, 1000); + /* 通过SIO接口发送数据,像SLIP一样 */ + u32_t bytes_written = sio_write(g_serial_ctx.sio_fd, (u8_t*)data, length); - if (bytes_written < 0) { - PPP_DEBUG_ERROR("UART write failed: %d", bytes_written); - g_serial_ctx.tx_errors++; - return PPP_ERR_UART; - } - - if ((uint32_t)bytes_written != length) { - PPP_DEBUG_WARN("Partial write: %d/%u bytes", bytes_written, length); + if (bytes_written != length) { + PPP_DEBUG_ERROR("SIO write failed: %u/%u bytes", bytes_written, length); g_serial_ctx.tx_errors++; return PPP_ERR_UART; } - g_serial_ctx.tx_bytes += (uint32_t)bytes_written; - PPP_DEBUG_DEBUG("Sent %u bytes successfully", bytes_written); + g_serial_ctx.tx_bytes += bytes_written; + PPP_DEBUG_DEBUG("Sent %u bytes successfully via SIO", bytes_written); return PPP_ERR_OK; } @@ -453,4 +355,13 @@ static uint32_t ppp_serial_buffer_available_space(void) static uint32_t ppp_serial_buffer_data_count(void) { return g_serial_ctx.rx_count; +} + +/** + * @brief 获取PPP模块SIO句柄 + * @return SIO句柄,如果未初始化则返回NULL + */ +sio_fd_t ppp_get_sio_fd(void) +{ + return g_serial_ctx.sio_fd; } \ No newline at end of file