You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Serial PPPoS会话无法响应Ping请求的技术求助

PPPoS Session with Telit GL865 & STM32F7: Ping Fails After Session Establishment

Let's break down your issue and walk through targeted troubleshooting steps and fixes based on the details you shared.

Problem Background

I'm working with an STM32F7 MCU connected to a Telit GL865 GSM module over UART (using STM32CubeMX + Keil for development). Here's what's working and what's not:

  • ✅ Using AT commands via the GSM module's internal stack, I can successfully get an IP address and ping external hosts.
  • ❌ After starting an LwIP PPPoS session, I can't ping the assigned PPP IP (5.26.61.173). The LwIP stack assigns a gateway of 192.168.202.0 and subnet mask 255.255.255.255 (a special value auto-assigned by LwIP).
  • Additional observations:
    • The MCU and GSM module send periodic "~y " data to each other after the session is established.
    • Ping attempts trigger communication between the two devices, but no response is returned.
    • I'm using interrupt-driven UART reception: when no new data is received for 10ms, the buffer is passed to pppos_input_tcpip.

Relevant Code Snippet

/* Includes ------------------------------------------------------------------*/ 
#include "FreeRTOS.h"
#include "task.h"
#include "cmsis_os.h"
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include "string.h"
#include "main.h"
#include "stm32f7xx_hal.h"
#include "cmsis_os.h"
#include "lwip.h"
#include "usart.h"
#include "gpio.h"
#include <stdio.h>
#include "string.h"
#include <time.h>
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/timeouts.h"
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/init.h"
#include "lwip/tcpip.h"
#include "lwip/netif.h"
#include "lwip/api.h"
#include "lwip/tcp.h"
#include "lwip/udp.h"
#include "lwip/dns.h"
#include "lwip/dhcp.h"
#include "lwip/autoip.h"
#include "lwip/etharp.h"
#include "netif/ethernet.h"
#include "lwip/apps/netbiosns.h"
#include "lwip/apps/httpd.h"
#include "lwip/sio.h"
#include "pppapi.h"
#include <lwip/sockets.h>
#include "usart.h"
#include "test.h"

#define RX_SIZE 4096 

/* USER CODE END Includes */ 

/* Variables -----------------------------------------------------------------*/ 
osThreadId defaultTaskHandle; 

/* USER CODE BEGIN Variables */ 
uint8_t lcpBuffer[RX_SIZE];
uint8_t lcpBufferIndex, quantityOfPackages = 0;
uint8_t pppBuffer[4096];
uint32_t sysTickCounter = 0;
uint8_t sendData[50] = " \n";
uint8_t recData, recDataOlder, recDataOlder2,recDataOlder3,recDataOlder4,recDataOlder5,recDataOlder6;
uint8_t receivedValue,connected,called = 0;
uint32_t recIndex = 0;
uint8_t recBuffer[RX_SIZE];
uint8_t sent, send, connect, connectionStatus, endOfLcpNegotiation, NCPNegotiation = 0;
ppp_pcb *ppp;
struct netif ppp_netif;
u8_t sio_idx = 0;
sio_fd_t ppp_sio;
uint8_t ATconnected,lcpCame,length = 0;
uint8_t lcpStartIndex, lcpStopIndex, lcpStartOld, lcpStart, lcpStop, dataReceived, timeOut, fillThePPPBuffer, gsmInitEnd, sendLCP, sendNCP, socketOpened, socketBind, socketOpen = 0;
uint32_t pppBufferIndex = 0;
ip4_addr_t addr;
int socketStatus;
int socket_fd,accept_fd;
int addr_size,sent_data;
char data_buffer[80];
struct sockaddr_in sa,ra,isa;
uint32_t runTimeCnt = 0;

void StartDefaultTask(void const * argument);
extern void MX_LWIP_Init(void);
void MX_FREERTOS_Init(void);

//PPP function
static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) {
    struct netif *pppif = ppp_netif(pcb);
    called = 1;
    switch(err_code) {
        case PPPERR_NONE: {
            connectionStatus = 1;
            printf("status_cb: Connected\n");
            printf(" our_ipaddr = %s\r\n", ipaddr_ntoa(&pppif->ip_addr));
            printf(" gatewayaddr = %s\r\n", ipaddr_ntoa(&pppif->gw));
            printf(" netmask = %s\r\n", ipaddr_ntoa(&pppif->netmask));
            break;
        }
        case PPPERR_PARAM: {
            connectionStatus = 2;
            printf("status_cb: Invalid parameter\r\n");
            break;
        }
        case PPPERR_OPEN: {
            connectionStatus = 3;
            printf("status_cb: Unable to open PPP session\r\n");
            break;
        }
        case PPPERR_DEVICE: {
            connectionStatus = 4;
            printf("status_cb: Invalid I/O device for PPP\r\n");
            break;
        }
        case PPPERR_ALLOC: {
            connectionStatus = 5;
            printf("status_cb: Unable to allocate resources\r\n");
            break;
        }
        case PPPERR_USER: {
            connectionStatus = 6;
            ppp_free(pcb);
            printf("status_cb: User interrupt\r\n");
            break;
        }
        case PPPERR_CONNECT: {
            connectionStatus = 7;
            // Truncated in original code
            break;
        }
    }
}

Troubleshooting & Fixes

1. Validate Subnet Mask & PPP Configuration

The subnet mask 255.255.255.255 is normal for point-to-point PPP links, so that's not the issue. But double-check your lwipopts.h to ensure critical PPP flags are enabled:

#define PPP_SUPPORT                  1
#define PPPOS_SUPPORT                1
#define PPP_POINTTOPOINT             1
#define LWIP_ICMP                    1  // Required for ping
#define PPP_IPV4_SUPPORT             1
#define PPP_DEBUG                    LWIP_DBG_ON  // Enable debug logs to spot negotiation issues

2. Fix UART Data Handling

Your 10ms timeout-based buffer submission can split or merge PPP frames, causing LwIP to fail parsing. PPP frames are wrapped in 0x7E flags—switch to frame-boundary detection instead:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == USARTx) {
        static uint8_t in_ppp_frame = 0;
        static uint32_t frame_start_idx = 0;

        // Detect PPP frame boundaries
        if (recData == 0x7E) {
            if (in_ppp_frame) {
                // End of frame: pass complete buffer to LwIP
                uint32_t frame_len = recIndex - frame_start_idx + 1;
                if (frame_len > 2) {  // Skip empty frames
                    pppos_input_tcpip(ppp_sio, &recBuffer[frame_start_idx], frame_len);
                }
                in_ppp_frame = 0;
            } else {
                // Start of frame: reset buffer index
                in_ppp_frame = 1;
                frame_start_idx = recIndex;
            }
        }

        // Only store data if we're inside a valid PPP frame
        if (in_ppp_frame) {
            recBuffer[recIndex++] = recData;
            if (recIndex >= RX_SIZE) recIndex = 0;  // Prevent overflow
        }

        // Restart interrupt reception
        HAL_UART_Receive_IT(&huart, &recData, 1);
    }
}

Also, filter out the periodic "~y " data—it's not part of PPP frames and will corrupt LwIP's input.

3. Verify Network Interface Setup

Ensure your PPP netif is properly registered as the default route:

// After creating the PPP PCB
netif_add(&ppp_netif, NULL, NULL, NULL, NULL, pppos_init, tcpip_input);
netif_set_default(&ppp_netif);
netif_set_up(&ppp_netif);

4. Enable Hardware Flow Control

Telit GL865 often requires RTS/CTS flow control for PPP to prevent data loss. Enable it in your STM32 UART configuration and set the module's AT command:

AT&K3  // Enable RTS/CTS hardware flow control

5. Debug PPP Negotiation

Turn on LwIP's PPP debug logs (via PPP_DEBUG) and monitor the UART output. Look for:

  • Successful LCP and NCP negotiation steps
  • No errors like "frame check sequence failure" or "invalid protocol"
  • Confirm that the module is forwarding ICMP ping responses back to the MCU

内容的提问来源于stack exchange,提问作者Sarp Engin Daltaban

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:45:07