我使用GSM模块Telit GL865进行UART通信,使用STM32F7 MCU和软件STM32CubeMX,Keil。
当我通过UART向AT模块发送AT命令时,我通过GSM模块的内部堆栈获取IP地址并成功ping通:
AT
AT&K0
AT#SCFG=3,1,300,600,300,10
AT+CGDCONT=1,"IP","mgbs","0.0.0.0",0,0
AT+CGSN
AT#ICMP=2
AT#GPPPCFG="000.000.000.000",25,1
AT#GPPPCFGEXT=0
ATDT*99#
CONNECT
但是,当我启动PPPoS会话时,我无法ping通通过PPP成功建立的IP。
通过PPP堆栈建立的IP,网关和网络掩码地址如下:
IP = 5.26.61.173
Gateway = 192.168.202.0
Netmask = 255.255.255.255
我看到的第一个问题是网络掩码地址;但是,LwIP PPPoS确立了这一点。
其次,在上面建立之后,MCU和GSM模块开始以"~y "
的形式发送周期性数据,长度分别为49和53.
这意味着我对printf( )
的调试无法向我显示所有定期数据。
第三,最重要的,当我ping上面的GSM的IP时,长度为68的周期数据"~y "
在MCU和GSM之间发送的时间要多得多,意味着 ping可触发GSM与MCU之间的通信,但无响应。
我使用基于中断的UART收发,它开始填充接收缓冲区并将其放入pppos_input_tcpip(ppp, recBuffer, recIndex)
,除非10ms内有新数据。
主线程和定时器中断如下:
/* 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 "ppp/ppp.h"
//#include "netif/ppp/pppapi.h"
//#include "netif/ppp/pppos.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); /* (MISRA C 2004 rule 8.1) */
//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;
printf("status_cb: Connection lost\r\n");
break;
}
case PPPERR_AUTHFAIL: {
connectionStatus = 8;
printf("status_cb: Failed authentication challenge\r\n");
break;
}
case PPPERR_PROTOCOL: {
connectionStatus = 9;
printf("status_cb: Failed to meet protocol\r\n");
break;
}
case PPPERR_PEERDEAD: {
connectionStatus = 10;
printf("status_cb: Connection timeout\r\n");
break;
}
case PPPERR_IDLETIMEOUT: {
connectionStatus = 11;
printf("status_cb: Idle Timeout\r\n");
break;
}
case PPPERR_CONNECTTIME: {
connectionStatus = 12;
printf("status_cb: Max connect time reached\r\n");
break;
}
case PPPERR_LOOPBACK: {
connectionStatus = 13;
printf("status_cb: Loopback detected\r\n");
break;
}
default: {
connectionStatus = 14;
printf("status_cb: Unknown error code %d\r\n", err_code);
break;
}
}
}
//PPP function
static u32_t output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx){
printf("sent: %s with length: %d\r\n",data,len);
return HAL_UART_Transmit_IT(&huart1, data, len);
}
/* Init FreeRTOS */
void MX_FREERTOS_Init(void) {
/* Create the thread(s) */
/* definition and creation of defaultTask */
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 1024);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
}
/* StartDefaultTask function */
void StartDefaultTask(void const * argument)
{
/* init code for LWIP */
MX_LWIP_Init();
/* USER CODE BEGIN StartDefaultTask */
//SysTick_Config(SystemCoreClock/1000);
HAL_UART_Receive_IT(&huart1, &recData, 1);
// Start of AT commands
HAL_Delay(1000);
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT\r\n", strlen("AT\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT&K0\r\n", strlen("AT&K0\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT#SCFG=3,1,300,600,300,10\r\n", strlen("AT#SCFG=3,1,300,600,300,10\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT#SLED=2,2,2\r\n", strlen("AT#SLED=2,2,2\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT#SLEDSAV\r\n", strlen("AT#SLEDSAV\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT+CGDCONT=1,\"IP\",\"mgbs\",\"0.0.0.0\",0,0\r\n", strlen("AT+CGDCONT=1,\"IP\",\"mgbs\",\"0.0.0.0\",0,0\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT+CGSN\r\n", strlen("AT+CGSN\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT#ICMP=2\r\n", strlen("AT#ICMP=2\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT+CSQ\r\n", strlen("AT+CSQ\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT+CCLK?\r\n", strlen("AT+CCLK?\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT#SGACT?\r\n", strlen("AT#SGACT?\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT#SGACT=1,0\r\n", strlen("AT#SGACT=1,0\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT#SGACT=1,1\r\n", strlen("AT#SGACT=1,1\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT#SGACT?\r\n", strlen("AT#SGACT?\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT#FRWL=1,\"10.0.1.1\",\"255.255.0.0\"\r\n", strlen("AT#FRWL=1,\"10.0.1.1\",\"255.255.0.0\"\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT#GPPPCFG=\"000.000.000.000\",25,1\r\n", strlen("AT#GPPPCFG=\"000.000.000.000\",25,1\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT#GPPPCFGEXT=0\r\n", strlen("AT#GPPPCFGEXT=0\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"AT#GAUTH=0\r\n", strlen("AT#GAUTH=0\r\n"));
HAL_Delay(1000);
memset(recBuffer, 0, sizeof(recBuffer));
recIndex = 0;
HAL_UART_Transmit_IT(&huart1, (uint8_t*)"ATDT*99***1#\r\n", strlen("ATDT*99***1#\r\n"));
//End of AT commands
//Start PPP
ppp = pppapi_pppos_create(&ppp_netif, output_cb, status_cb, NULL);
if (ppp == NULL) {
printf("Error init pppos");
return;
}
pppapi_set_default(ppp);
ppp_set_auth(ppp, PPPAUTHTYPE_NONE, "", "");
pppapi_listen(ppp);
for(;;)
{
//if GSM is initialized, give data to ppp if stops coming after 10ms,
//send flag is set by systick(10ms) and gsmInitEnd is set after LCP session starts
if(gsmInitEnd){
if(send){
send = 0;
pppos_input_tcpip(ppp, recBuffer, recIndex);
printf("received: %s with length: %d\r\n", recBuffer, recIndex);
recIndex = 0;
runTimeCnt++;
memset(recBuffer, 0, sizeof(recBuffer));
}
}
}
}
// UART rx callback, called over 1 data received
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
if (UartHandle->Instance == USART1)
{
//callback reset
HAL_UART_Receive_IT(&huart1, &recData, 1);
//receive buffer overflow check
if(recIndex >= RX_SIZE){
recIndex = 0;
}
//3 variables below are externed to send data if stops coming to
//buffer after 10ms with Systick interrupt later than GSM initialization
dataReceived = 1;
sysTickCounter = 0;
send = 0;
//LCP packets start with 0x7E, that means the end of GSM initialization.
if(recData == 0x7E)
{
if(gsmInitEnd == 0){
recIndex = 0;
memset(recBuffer, 0, sizeof(recBuffer));
}
gsmInitEnd = 1;
}
recBuffer[recIndex++] = recData;
}
}
Systick Handler检查RX缓冲区并设置发送标志,以便在10ms后数据停止时将数据发送到ppp:
void SysTick_Handler(void)
{
if(dataReceived){
sysTickCounter++;
if (sysTickCounter >= 10)
{
send = 1;
dataReceived = 0;
sysTickCounter = 0;
}
}
osSystickHandler();
}
GSM和STM32之间的数据通信对我来说似乎没问题(!)并且通过ping请求触发;但是,没有ping响应..
在我看来,问题可能是关于ppp_netif
和ppp_netif(ppp)
之间的连接,网络掩码或ping实现的LwIP堆栈......
答案 0 :(得分:0)
答案是激活STM32CubeMX的传出和传入ICMP校验和选项...因此,激活LWIP_ICMP模块本身不足以响应ping请求。
答案 1 :(得分:0)
如果为PPPOS启用软件校验和,则以太网会中断,因为STM32在以太网的硬件中执行它们-GRRR