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
}
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);
}
}
-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)
{
PRINTPKT_SUPPORT=1
PPP_DEBUG=LWIP_DBG_ON
PPP_INPROC_IRQ_SAFE=0
+ PPP_OPTIONS=1
SUPPORT_PPP_SERVICE
SUPPORT_AT_PPP
)
/* 配置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) {
*/
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状态
*/
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
/* 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
/* 缓冲区大小配置 */
#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大小
*/
void ppp_api_enable_cat1(bool isopen);
+/**
+ * @brief PPP模块反初始化
+ */
+void ppp_api_deinit(void);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
*/
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
#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"
// 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;
}
{
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;
}
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
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拨号命令
*/
*/
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;
}
/**
#include "ppp_types.h"
#include "ppp_debug.h"
#include "ppp_serial.h"
+#include "ppp_power_ctl.h" // 添加电源控制头文件
#include "securec.h"
#include <string.h>
#include "lwip/dns.h"
#include "netif/ppp/ppp.h"
#include "netif/ppp/pppos.h"
+#include "lwip/sio.h" // 添加SIO头文件
#endif
/* PPP lwIP上下文 */
}
/**
- * @brief PPP输出回调函数
+ * @brief PPP输出回调函数 - 使用SIO接口,像SLIP一样
*/
static u32_t ppp_lwip_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx)
{
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
*/
void ppp_api_uart_init(void)
{
- PPP_DEBUG_PRINT("PPP UART init\n");
- // UARTå\88\9då§\8bå\8c\96é\80»è¾\91å\8f¯ä»¥å\9c¨è¿\99é\87\8cæ·»å\8a
+ PPP_DEBUG_PRINT("PPP UART init - delegated to ppp_serial module\n");
+ // UARTå\88\9då§\8bå\8c\96é\80»è¾\91已移è\87³ppp_serial.cä¸
}
/**
// 可以在这里添加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
#include "securec.h"
#include <string.h>
+// 添加SIO相关头文件,让PPP像SLIP一样使用SIO接口
+#include "lwip/sio.h"
+#include "lwip/opt.h"
+
/* 串口上下文结构 */
typedef struct {
bool initialized;
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;
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;
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串口
*/
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));
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;
}
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