-

   rss_rss_hh_new

 - e-mail

 

 -

 LiveInternet.ru:
: 17.03.2011
:
:
: 51

:


[ ] STM32 + PPP (GSM) + LwIP

, 10 2017 . 08:55 +
GSM UART, AT-. , AT :





, , URC- , SMS, . , , . , AT , ,

SIM800C. PPP, . PPP, , AT , , .

PPP-:



PPP ~ (0x7E). , , . , PPP, LwIP. PPPOS PPPOE (Over serial Ethernet), PAP CHAP, .



-:


STM32 FreeRTOS.

, ,
int main(void) {
     HAL_Init();
     SystemClock_Config();
     MX_GPIO_Init();
     MX_DMA_Init();
     //  gsm,    LwIP
     InitGsmUart();
     //    -    
     xTaskCreate(StartThread, "Start", configMINIMAL_STACK_SIZE*2, 0, tskIDLE_PRIORITY+1, &taskInitHandle);
     //  
     osKernelStart(NULL, NULL);
     while (1) {}
}

void StartThread(void * argument) {
     gsmTaskInit();
     // , / 
     xTaskCreate(connectTask, "connectTask", configMINIMAL_STACK_SIZE*1, 0, tskIDLE_PRIORITY+1, NULL);
     //   
     vTaskDelete(NULL);
}


. ,
// - .    1,   ,   RAM    LwIP (  )
#define GSM_MAX_CONNECTION	1
//     
typedef struct{
     uint8_t *rxBuff;
     uint16_t rxLen;
}sBuff[GSM_MAX_CONNECTION];

sBuff buff = {0};
	
void connectTask(void *pServiceNum) {
     bool connectState = false;
     eRetComm status = eError;
     uint16_t delay = 0;
     uint8_t serviceNum = *(uint8_t*)pServiceNum;
     xSemaphoreHandle xRxPppData; //     ppp
     xRxPppData = GsmLLR_GetRxSemphorePoint(serviceNum);
	
     for(;;) {
     /*    */
     if(connectState == true) {
     //    
     while(GsmLLR_ConnectServiceStatus(serviceNum) == eOk) {
          //   	
          buff[serviceNum].rxLen = getRxData(serviceNum, xRxPppData,&(buff[serviceNum].rxBuff));
          if(buff[serviceNum].rxLen != 0) {
                    //     
                    if(GsmLLR_TcpSend(serviceNum, buff[serviceNum].rxBuff, 
buff[serviceNum].rxLen) == eOk) {
                    printf("Connect:#%i SendData OK\r\n", serviceNum);
          }else{
                    printf("Connect:#%i SendData ERROR\r\n", serviceNum);
                    connectState = false;	          
                    }
          }
     }
     //  
     printf("Connect:#%i connection lost\r\n", serviceNum);
     GsmLLR_DisconnectService(serviceNum);
     connectState = false;	
     delay = 1000;
     } else {
     //  , 
     printf("Connect:#%i connecting...", serviceNum);
     //  
     if(GsmLLR_ConnectService(serviceNum) == eOk) {
          printf("Connect:#%i connected", serviceNum);
          connectState = true;		
     } else { //   
          printf("Connect:#%i ERROR", serviceNum);				
          delay = GSM_CONNECTION_ERROR_DELAY;
          connectState = false;
          }
     }
     vTaskDelay(delay/portTICK_RATE_MS);
     }
}
//  
uint16_t getRxData(uint8_t serviceNum, xSemaphoreHandle xRxPppData, uint8_t **ppBufPacket) {
     uint16_t retLen = 0;
     uint16_t size = 0;
     if(xSemaphoreTake(xRxPppData, 1000/portTICK_PERIOD_MS) == pdTRUE) {
          size = gsmLLR_TcpGetRxCount(serviceNum);
          if(size > 1512) {
           retLen = 0;
          }else {
          retLen = GsmLLR_TcpReadData(serviceNum, ppBufPacket, size);
          }
     }
return retLen;
}


GSM,
void gsmTaskInit(void) {
     xTaskCreate(vGsmTask, "GSM", configMINIMAL_STACK_SIZE*2, 0, tskIDLE_PRIORITY+1, &gsmInitTaskId);
     while((!gsmState.init) || (!pppIsOpen)) {vTaskDelay(100/portTICK_PERIOD_MS);}
}

/*     GSM  */
void vGsmTask( void * pvParameters ) {
     //  
     GsmLLR_Init();
     GsmLLR2_Init();
     GsmPPP_Init();
     //    
     while((gsmState.initLLR != true) && (gsmState.initLLR2 != true)){};
     if(GsmLLR_PowerUp() != eOk) {
          GsmLLR_ModuleLost();
     }
     for(;;) {		
          // 
          if(gsmState.init == false) {
          //    
          if(gsmState.notRespond == true) {
               printf("GSM: INIT Module lost\r\n");
               GsmLLR_ModuleLost();
               continue;
          }
          //  
          if(GsmLLR_ATAT() != eOk) {
               gsmState.notRespond = true;
               continue;
          }
          //    
          if(GsmLLR_WarningOff() != eOk) {
               gsmState.notRespond = true;
               continue;
          }
          //  
          if(GsmLLR_FlowControl() != eOk) {
               gsmState.notRespond = true;
               continue;
          }
          //  IMEI
          if(GsmLLR_GetIMEI(aIMEI) != eOk) {
               gsmState.notRespond = true;
               continue;
          }
          DBGInfo("GSM: module IMEI=%s\r\n", aIMEI);
          //  IMSI
          if(GsmLLR_GetIMSI(aIMSI) != eOk) {
               gsmState.notRespond = true;
               continue;
          }			
          printf("GSM: module IMSI=%s\r\n", aIMSI);
          //  Software
          if(GsmLLR_GetModuleSoftWareVersion(aVerionSoftware) != eOk) {
               gsmState.notRespond = true;
               continue;
          }
          //      (URC)
          if(GsmLLR_AtCREG() != eOk) {
               gsmState.notRespond = true;
               continue;
          }
          printf("GSM: CREG OK\r\n");
          //   
          if(GsmLLR_UpdateCSQ(&gsmCsqValue) != eOk) {
               printf("GSM: Get CSQ ERROR, -RELOAD\r\n");
               gsmState.notRespond = true;
               continue;
          }else{
               printf("GSM: CSQ value %d\r\n", gsmCsqValue);
               //  SMS
               if(GsmLLR_SmsModeSelect(sms_TEXT) != eOk) {
                    gsmState.notRespond = true;
                    continue;
               }
               // sms
               vTaskDelay(DELAY_REPLY_INIT/portTICK_RATE_MS);
               if(GsmLLR_SmsClearAll() != eOk) {
                    printf("GSM: clear SMS ERROR, -RELOAD\r\n");
                    gsmState.notRespond = true;
                    continue;
               }
		printf("GSM: Clear SMS Ok\r\n");
			
               printf("GSM: INIT PPPP\r\n");
		if(GsmLLR_StartPPP(&connectionSettings.gsmSettings) == eOk) {
                    printf("GSM: INIT PPPP - PPP RUN\r\n");
                    xQueueReset(uartParcerStruct.uart.rxQueue);
                    uartParcerStruct.ppp.pppModeEnable = true;
                    uartParcerStruct.uart.receiveState = true;
                    gsmState.init = true;
               }else{
                    printf("GSM: INIT PPPP - PPP ERROR!!!\r\n");
                    gsmState.notRespond = true;
                    continue;
               }
          }
     }
     vTaskDelay(1000/portTICK_RATE_MS);
     }
}


PPP.

4 comPPP_0-4. , . :

char *comPPP_0[] = {"AT+CGDCONT=1,\"IP\","};
char *comPPP_2[] = {"AT+CGQMIN=1,0,0,0,0,0"};
char *comPPP_3[] = {"AT+CGQREQ=1,2,4,3,6,31"};
char *comPPP_4[] = {"ATD*99***1#"};

eRetComm GsmLLR_StartPPP(sGsmSettings *pSettings) {
	printf("StartPPP\r\n");
	sResultCommand resultCommand;
	char **comPPP_Mass[3] = {comPPP_2, comPPP_3, comPPP_4};
	uint8_t *pData = NULL;
	if(GsmLLR_GetMutex() == true) {
		pData = pvPortMalloc(GSM_MALLOC_COMMAND_SIZE);
		if(pData != NULL) {
			memset(pData, 0, GSM_MALLOC_COMMAND_SIZE);
			sprintf((char*)pData, "%s%s", comPPP_0[0], (char*)pSettings->gprsApn);
			RunAtCommand((char*)pData, &resultCommand);
			//  ,    
			uint8_t stepIndex = 0;
			while(stepIndex != (3)) {
				uint16_t len = strlen((char*)*comPPP_Mass[stepIndex]);
				sprintf((char*)pData, "%s", (char*)*comPPP_Mass[stepIndex]);
				RunAtCommand((char*)pData, &resultCommand);
				stepIndex++;
			}
			memset(pData, 0, GSM_MALLOC_COMMAND_SIZE);
			vPortFree(pData);
		}
		GsmLLR_GiveMutex();
	}
	return eOk;
}


vGsmTask, , GsmLLR_StartPPP pppModeEnable uartParcerStruct.uart.rxQueue. pppModeEnable . UART / .

PPP GSM
void GsmPPP_Tsk(void *pvParamter) {
	int timeout = 0;
	uint8_t i;
	bool stateInit = false;
	uint16_t tskStackInit;
	LwipStack_Init();
	pppInit();
	pppSetAuth(PPPAUTHTYPE_CHAP, connectionSettings.gsmSettings.gprsUser, connectionSettings.gsmSettings.gprsPass);
	sioWriteSemaphore = xSemaphoreCreateBinary();
	for(i=0; i/      PPP    
		if(uartParcerStruct.ppp.pppModeEnable == true) {
			if(!pppIsOpen) {
				pppNumport = pppOverSerialOpen(0, linkStatusCB, &pppIsOpen);
				pppStop = 0;
				timeout = 0;
				stateInit = false;
				while(timeout < 300) {
					if(pppIsOpen) {
						printf("PPP init - OK\r\n");
						lwip_stats.link.drop = 0;
						lwip_stats.link.chkerr = 0;
						lwip_stats.link.err = 0;
						stateInit = true;
						break;
					}else{
						timeout ++;
						vTaskDelay(100/portTICK_RATE_MS);
					}
				}
				if(stateInit != true) {
					printf("PPP init - TIMEOUT-ERROR\r\n");
					pppClose(pppNumport);
					pppIsOpen = false;
					uartParcerStruct.ppp.pppModeEnable = false;
					gsmState.init = false;
					gsmState.notRespond = true;
				}
			}else{
				if((lwip_stats.link.drop !=0) || (lwip_stats.link.chkerr !=0)) {
					lwip_stats.link.drop = 0;
					lwip_stats.link.chkerr = 0;
					printf("GSMM: DROPING FAIL!!! RESTART PPP\r\n");
					for(i=0; iportTICK_PERIOD_MS);
				}
			}
		}
		vTaskDelay(500/portTICK_RATE_MS);
	}
}


, PPP

Connect-Disconnect, , ..
bool GsmPPP_Connect(uint8_t numConnect, char *pDestAddr, uint16_t port) {	
	struct ip_addr resolved = {0};
	bool useDns = false;
	uint8_t ipCut[4] = {0};
	
	if(!pppIsOpen) {
		printf("GSMPPP: CONNECT ERROR - PPP closed\r\n");
		return false;
	}
	sscanf(pDestAddr, "%i.%i.%i.%i", &ipCut[0], &ipCut[1], &ipCut[2], &ipCut[3]);	
	if((ipCut[0]!=0)&&(ipCut[1]!=0)&&(ipCut[2]!=0)&&(ipCut[3]!=0)) {
		IP4_ADDR(&connectionPppStruct.ipRemoteAddr[numConnect], ipCut[0],ipCut[1],ipCut[2],ipCut[3]); //31,10,4,158);
		useDns = false;
	}else{
		useDns = true;
	}
	
	if(connectionPppStruct.connected[numConnect] == false) {
		connectionPppStruct.tcpClient[numConnect] = tcp_new();	// create tcpPcb	
		tcp_recv(connectionPppStruct.tcpClient[numConnect], server_recv);
		
		if(useDns == true) {
			switch(dns_gethostbyname(pDestAddr, &resolved, destServerFound, &numConnect)) {
			case ERR_OK: // numeric or cached, returned in resolved
				connectionPppStruct.ipRemoteAddr[numConnect].addr = resolved.addr;
				break;
			case ERR_INPROGRESS: // need to ask, will return data via callback
				if(xSemaphoreTake(connectionPppStruct.semphr[numConnect], 10000/portTICK_PERIOD_MS) != pdTRUE) {
					while(tcp_close(connectionPppStruct.tcpClient[numConnect]) != ERR_OK) { vTaskDelay(100/portTICK_PERIOD_MS); }
					connectionPppStruct.connected[numConnect] = false;
					printf("GSMPPP: dns-ERROR\r\n");
				return false;
				}else{ }
				break;
			}
		}
		tcp_connect(connectionPppStruct.tcpClient[numConnect], &connectionPppStruct.ipRemoteAddr[numConnect], port, &TcpConnectedCallBack);
		if(xSemaphoreTake(connectionPppStruct.semphr[numConnect], 10000/portTICK_PERIOD_MS) == pdTRUE) {
			connectionPppStruct.connected[numConnect] = true;
			printf("GSMPPP: connected %s\r\n", inet_ntoa(connectionPppStruct.ipRemoteAddr));
			return true;
		}else{
tcp_abort(connectionPppStruct.tcpClient[numConnect]);//tcp_close(connectionPppStruct.tcpClient[numConnect]);
			while(tcp_close(connectionPppStruct.tcpClient[numConnect]) != ERR_OK) { vTaskDelay(100/portTICK_PERIOD_MS); }
			printf("GSMPPP: connectTimeout-ERROR\r\n");
			return false;
		}		
	}else{
		if(GsmLLR_ConnectServiceStatus(numConnect) == eOk) {
			printf("GSMPPP: CONNECT-already connected %s\r\n", inet_ntoa(connectionPppStruct.ipRemoteAddr));
			return true;
		}else{
			printf("GSMPPP: CONNECT CLOSE!!!\r\n");
			return false;
		}
	}
	return false;
}

bool GsmPPP_Disconnect(uint8_t numConnect) {
	if(!pppIsOpen) {
		printf("GSMPPP: CONNECT ERROR - PPP closed\r\n");
		return false;
	}
	if(connectionPppStruct.tcpClient[numConnect] == NULL) {
		return false;
	}
	while(tcp_close(connectionPppStruct.tcpClient[numConnect]) != ERR_OK) { vTaskDelay(100/portTICK_PERIOD_MS); }
	connectionPppStruct.connected[numConnect] = false;
	return true;
}

bool GsmPPP_ConnectStatus(uint8_t numConnect) {
	if(!pppIsOpen) {
		printf("GSMPPP: CONNECT ERROR - PPP closed\r\n");
		return false;
	}
	if(connectionPppStruct.tcpClient[numConnect]->state == ESTABLISHED) {
		return true;
	}
	return false;
}

bool GsmPPP_SendData(uint8_t numConnect, uint8_t *pData, uint16_t len) {
	if(!pppIsOpen) {
		printf("GSMPPP: CONNECT ERROR - PPP closed\r\n");
		return false;
	}
	if(tcp_write(connectionPppStruct.tcpClient[numConnect], pData, len, NULL) == ERR_OK) {
		return true;
	}else {
		while(tcp_close(connectionPppStruct.tcpClient[numConnect]) != ERR_OK) { vTaskDelay(100/portTICK_PERIOD_MS); }
		connectionPppStruct.connected[numConnect] = false;
		connectionPppStruct.rxData[numConnect].rxBufferLen = 0;
		memset(connectionPppStruct.rxData[numConnect].rxBuffer,0, sizeof(connectionPppStruct.rxData[numConnect].rxBuffer));
	}
	return false;
}

uint16_t GsmPPP_GetRxLenData(uint8_t numConnect) {
	if(!pppIsOpen) {
		printf("GSMPPP: CONNECT ERROR - PPP closed\r\n");
		return false;
	}
	return connectionPppStruct.rxData[numConnect].rxBufferLen;
}

uint16_t GsmPPP_ReadRxData(uint8_t numConnect, uint8_t **ppData) {
	if(!pppIsOpen) {
		printf("GSMPPP: CONNECT ERROR - PPP closed\r\n");
		return false;
	}
	if(connectionPppStruct.rxData[numConnect].rxBufferLen != 0) {
		*ppData = (uint8_t *) connectionPppStruct.rxData[numConnect].rxBuffer;
		uint16_t retLen = connectionPppStruct.rxData[numConnect].rxBufferLen;
		connectionPppStruct.rxData[numConnect].rxBufferLen = 0;
		return retLen;
	}
	return false;
}

static void destServerFound(const char *name, struct ip_addr *ipaddr, void *arg)
{
	uint8_t *num = (uint8_t*)arg;
	if(*num < SERVERS_COUNT) {
		printf("GSMPPP: DEST FOUND %s\r\n", inet_ntoa(ipaddr->addr));
		connectionPppStruct.ipRemoteAddr[num].addr = ipaddr->addr;
		xSemaphoreGive(connectionPppStruct.semphr[num]);	
	}else{
		printf("GSMPPP: DNS != SERVER%s\r\n", inet_ntoa(ipaddr->addr));
	}
}

static err_t TcpConnectedCallBack(void *arg, struct tcp_pcb *tpcb, err_t err) {
	for(uint8_t i=0; ilocal_ip.addr));
			xSemaphoreGive(connectionPppStruct.semphr[i]);
			break;
		}
	}
}

static err_t server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
   LWIP_UNUSED_ARG(arg);

	if(err == ERR_OK && p != NULL) {
		tcp_recved(pcb, p->tot_len);
		printf("GSMPPP:server_recv(): pbuf->len %d byte\n [%s]", p->len, inet_ntoa(pcb->remote_ip.addr));
    
		for(uint8_t i=0; iremote_ip.addr == connectionPppStruct.tcpClient[i]->remote_ip.addr) {
				printf("GSMPPP: server_recv (callback) [%s]\r\n", inet_ntoa(pcb->remote_ip.addr));
				if(p->len < sizeof(connectionPppStruct.rxData[i].rxBuffer)) {
					memcpy(connectionPppStruct.rxData[i].rxBuffer, p->payload, p->len);
					connectionPppStruct.rxData[i].rxBufferLen = p->len;
					xSemaphoreGive(connectionPppStruct.rxData[i].rxSemh);
					printf("GSMPPP: server_recv (callback) GIVE SEMPH[%s][%d]\r\n", inet_ntoa(pcb->remote_ip.addr), p->len);
				}else{
					printf("GSMPPP: server_recv p->len > sizeof(buf) -ERROR\r\n");
				}
			}
		}
    pbuf_free(p);
	}else{
		printf("\nserver_recv(): Errors-> ");
    if (err != ERR_OK)
			printf("1) Connection is not on ERR_OK state, but in %d state->\n", err);
		if (p == NULL)
			printf("2) Pbuf pointer p is a NULL pointer->\n ");
    printf("server_recv(): Closing server-side connection...");
		pbuf_free(p);
    server_close(pcb);
	}
   return ERR_OK;
}

xSemaphoreHandle * GsmPPP_GetRxSemaphorePoint(uint8_t numService) {
	return (connectionPppStruct.rxData[numService].rxSemh);
}


TCP LwIP, callback-s
static err_t server_poll(void *arg, struct tcp_pcb *pcb)
{
   static int counter = 1;
   LWIP_UNUSED_ARG(arg);
   LWIP_UNUSED_ARG(pcb);
   printf("\nserver_poll(): Call number %d\n", counter++);
   return ERR_OK;
}

static err_t server_err(void *arg, err_t err)
{
   LWIP_UNUSED_ARG(arg);
   LWIP_UNUSED_ARG(err);
   printf("\nserver_err(): Fatal error, exiting...\n");
   return ERR_OK;
}

static void server_close(struct tcp_pcb *pcb)
{
	tcp_arg(pcb, NULL);
	tcp_sent(pcb, NULL);
	tcp_recv(pcb, NULL);
while(tcp_close(pcb) != ERR_OK) { vTaskDelay(100/portTICK_PERIOD_MS); }
	for(uint8_t i=0; ilocal_ip.addr));
			connectionPppStruct.connected[i] = false;
		}else{
			printf("GSMPPP: server_recv p->len > sizeof(buf) -ERROR\r\n");
		}
	}
}


LwIP UART GSM ,
//      -    LwIP
u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len)
{
	unsigned long i = 0;
	if(uartParcerStruct.ppp.pppModeEnable) {
		while(xQueueReceive(uartParcerStruct.uart.rxQueue,&data[i], 0) == pdTRUE) {
			if(i==0) {
				printf("Reading PPP packet from UART\r\n");
			}
			printf("%0.2x ", data[i]);
			i++;
			if (pppStop||(i==len)) {
				pppStop = false;
				return i;
			}
		}
		if (i>0) {
			printf("\n");
		}
	}
	return i;
}
//   LwIP  UART (GSM)
u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len)
{
	u32_t retLen = 0;
	if(uartParcerStruct.ppp.pppModeEnable) {
		if(HAL_UART_Transmit_IT(&huart3, data, len) == HAL_OK) {
			xSemaphoreTake(sioWriteSemaphore, portMAX_DELAY);
			retLen = len;
		}else{
			printf("HAL ERRROR WRITE [sio_write]\r\n");
		}
	}else{
		printf("sio_write not in PPP mode!\r\n");
	}
	return retLen;
}
//  ,  
void sio_read_abort(sio_fd_t fd)
{
	pppStop = true;
	xQueueReset(uartParcerStruct.uart.rxQueue);
}

u32_t sys_jiffies(void) {
	return xTaskGetTickCount();
}
//         
static void linkStatusCB(void * ctx, int errCode, void * arg) {
	printf("GSMPP: linkStatusCB\r\n"); /* just wait */
	bool *connected = (bool*)ctx;
	struct ppp_addrs * addrs = arg;
	switch (errCode) {
		case PPPERR_NONE: { /* We are connected */
			printf("ip_addr = %s\r\n", inet_ntoa(addrs->our_ipaddr));
			printf("netmask = %s\r\n", inet_ntoa(addrs->netmask));
			printf("dns1 = %s\r\n", inet_ntoa(addrs->dns1));
			printf("dns2 = %s\r\n", inet_ntoa(addrs->dns2));
			*connected = 1;
			break;
		}
		case PPPERR_CONNECT: {
			printf("lost connection\r\n"); /* just wait */
			*connected = 0;
			break;
		}
		default: { /* We have lost connection */
			printf("connection error\r\n"); /* just wait */
			*connected = 0;
			break;
		}
	}
}


TCP :



:



.

AT-, , ( ) , URC . AT- APN.

PPP, , .
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332742/

:  

: [1] []
 

:
: 

: ( )

:

  URL