Jump to content

    
Sign in to follow this  
Алексей ВМ

STM32F4 + FreeRTOS + lwip + pppos + usb modem

Recommended Posts

Добрый день!

Есть задача передать на сервер данные. Используется STM32F4 с FreeRTOS и lwIP. К STM посредством USB подключен модем.  В lwIP включена поддержка PPPoS для работы с модемом. Запись данных и ожидание результата производится в отдельной задаче. Данные передаются, но подтверждение от сервера часто (в 90% случаев) приходит в течении нескольких секунд (2-8), а иногда вообще данные до сервера не доходят. При использовании Ethernet таких проблем на данной плате с данным сервером нет.  Может, кто сталкивался с подобной проблемой, в какую сторону копать?

 

Edited by Алексей ВМ

Share this post


Link to post
Share on other sites
25 минут назад, Алексей ВМ сказал:

Может, кто сталкивался с подобной проблемой, в какую сторону копать?

Часто такое происходит при ошибках в функциях ввода-вывода в модем. Включать в lwip отладочный вывод с подробной распечаткой содержимого пакетов и искать в этих распечатках какие-то корреляции с проблемами.

Отвлечение: По USB модем к lwip не подключал, только через УСАПП. Можно кратенько (или подробнее) о вашем решении: какой модем, как программно организовано это подключение?

Share this post


Link to post
Share on other sites
21 minutes ago, Сергей Борщ said:

Отвлечение: По USB модем к lwip не подключал, только через УСАПП. Можно кратенько (или подробнее) о вашем решении: какой модем, как программно организовано это подключение?

Если кратко, то Модем - HUAWEI E3372h, АТ команды - с использованием CDC поверх USB.

 

PPP_Conn = pppos_create(&ppp_netif, PPPoutputCB, PPPlinkStatusCB, &GLOB_PPP_ConnStatus);

static u32_t PPPoutputCB(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx)
{
    return USBH_CDC_SendData(data, len);
}

Прием

USBH_BulkReceiveData(&USB_OTG_Core,&bDatIN[datPtr],64,MSC_Machine.hc_num_in);

xTaskCreate(vUSBH, "vtUSBH", configMINIMAL_STACK_SIZE, NULL, 0, NULL);
xTaskCreate(vUSBHrx, "vtUSBHrx", configMINIMAL_STACK_SIZE, NULL, 3, NULL);
        
xTaskCreate(vlwIP_PPPinit, "vtlwIP_PPPinit", configMINIMAL_STACK_SIZE, NULL, 0, NULL);


void vUSBH(void *pvParameters)
{       
    USBH_Init(&USB_OTG_Core,USB_OTG_HS_CORE_ID,&USB_Host,&USBH_MSC_cb,&USR_Callbacks);
   
    while (1)
    {
            USBH_Process(&USB_OTG_Core, &USB_Host);
    }
}

void vUSBHrx(void *pvParameters) 
{
	uint32_t datPtr=0;
	
	while (1) 
	{
		if (usbUP == 1) 
		{
				taskENTER_CRITICAL();
				USBH_BulkReceiveData(&USB_OTG_Core,&bDatIN[datPtr],64,MSC_Machine.hc_num_in);
				taskEXIT_CRITICAL();
			
			if (xSemaphoreTake(SemRxURB_DONE,(200/portTICK_RATE_MS))==pdPASS) 
			{ //If URB status is set to URB_DONE in interrupt service routine
				DatIN=HCD_GetXferCnt(&USB_OTG_Core,MSC_Machine.hc_num_in);
				
				if (GLOB_PPP_ConnStatus>=20) 
				{ //if already in PPP mode
					if ((DatIN>=64)&&(datPtr<(64*3))) 
					{
						datPtr+=DatIN;
						DatIN=0;
					} 
					else if ((DatIN+datPtr)>0) 
					{
						pppos_input_tcpip(PPP_Conn,bDatIN,(DatIN+datPtr));
						DatIN=0;
						datPtr=0;
					} 
				} 
				else 
				{ //if not in PPP mode yet
					if ((DatIN>=64)&&(datPtr<(64*3))) 
					{
						datPtr+=DatIN;
						DatIN=0;
					} 
					else if ((DatIN+datPtr)>0) 
					{
						DatIN=DatIN+datPtr;
						datPtr=0;
					}
				}
			}
		} 
		else 
		{
				vTaskDelay(100/portTICK_RATE_MS);
		}
	}
}

void OTG_HS_IRQHandler(void) 
{
		static signed portBASE_TYPE xHPTW; //GSH addon
		USBH_OTG_ISR_Handler(&USB_OTG_Core);

		if (usbUP != 0) 
		{
				if (HCD_GetURB_State(&USB_OTG_Core, MSC_Machine.hc_num_in) == URB_DONE)
				{
						USB_OTG_Core.host.URB_State[MSC_Machine.hc_num_in] = URB_IDLE;
						xSemaphoreGiveFromISR(SemRxURB_DONE,&xHPTW);
						portYIELD_FROM_ISR(xHPTW);
				}
		}
}

 

При включении LWIP_STATS появляются ошибки tcp drop и proterr. А вот куда дальше копать - пока в затруднении

Edited by Алексей ВМ

Share this post


Link to post
Share on other sites
18 минут назад, Алексей ВМ сказал:

АТ команды - с использованием CDC поверх USB.

cmux не поднимали? Или модем определяется как несколько CDC?
 

 

20 минут назад, Алексей ВМ сказал:

При включении LWIP_STATS

Я имел ввиду PPP_DEBUG и PRINTPKT_SUPPORT.

Share this post


Link to post
Share on other sites
2 minutes ago, Сергей Борщ said:

cmux не поднимали? Или модем определяется как несколько CDC?

cmux не задействован. CDC скорей всего один. Код обмена с модемом писал не я, могу ошибаться. CDC используется для AT команд управления, а данные читаются/пишутся c помощью MSC.

Инициализация USB хоста

 

USBH_Init(&USB_OTG_Core,USB_OTG_HS_CORE_ID,&USB_Host,&USBH_MSC_cb,&USR_Callbacks);
USBH_Class_cb_TypeDef  USBH_MSC_cb = 
{
  USBH_MSC_InterfaceInit,
  USBH_MSC_InterfaceDeInit,
  USBH_MSC_ClassRequest,
  USBH_MSC_Handle,
};

хм, инициализируется только MSC. Мне кажется, CDC тут фиктивный(?).

Вот код передачи по CDC. Видно, что используется MSС.

uint32_t USBH_CDC_SendData(uint8_t *data, uint32_t len) 
{	
		URB_STATE 	urb_tx = URB_IDLE;
		uint32_t 		i = 0;
		uint32_t 		size = 0;
		uint8_t			txState = 0;
		uint8_t			j;
		
		while (i < len) 
		{
				urb_tx = HCD_GetURB_State(&USB_OTG_Core, MSC_Machine.hc_num_out);
				
				switch (txState) 
				{
					case 0: //Prepare and send data
							switch (urb_tx) 
							{
									case URB_DONE:
									case URB_IDLE:
									case URB_NOTREADY:
										if ((len - i) > MSC_Machine.MSBulkOutEpSize) 
										{
												size = MSC_Machine.MSBulkOutEpSize;
										} 
										else 
										{
												size = (len - i);
										}
										
										taskENTER_CRITICAL();
										USBH_BulkSendData(&USB_OTG_Core, (data + i), size, MSC_Machine.hc_num_out);
										taskEXIT_CRITICAL();
										
										txState = 1;
										
										j = 0;
										break;
							}
							break;
						
					case 1:
							switch (urb_tx)
							{
									case URB_DONE:
										i += size;
										txState = 0;
										break;
									
									case URB_NOTREADY:
										txState = 0;
										//printf("\nUSB_TX_NOTREADY");
										vTaskDelay(1/portTICK_RATE_MS); //def 5
										break;
									
									case URB_IDLE:		
										txState = 0; // AlexM 181118	
										break;
									
									case URB_ERROR:
										vTaskDelay(1/portTICK_RATE_MS);
										printf("\nUSB_TX_ERR_TOUT");
										j++;
									
										if (j >= 5) 
										{
												i += size; 
												txState = 0;
												printf("\nUSB_TX_ERR");
										}
										break;	
							}				
							break;
				}
		}
		//printf("\nlen=%u, sent=%u",len,i);
		return i;
}

 

Share this post


Link to post
Share on other sites

Воткнул модем в ноут - COM портов нет. Думаю, модем каким-то хитрым образом сконфигурирован.

Дров не было. Установил - появился СОМ порт.

Edited by Алексей ВМ

Share this post


Link to post
Share on other sites
1 час назад, Алексей ВМ сказал:

Воткнул модем в ноут - COM портов нет. Думаю, модем каким-то хитрым образом сконфигурирован.

Эти модемы насколь помню, типа "HiLink-модем" задействуют особый режим наподобии RNDIS только как хост, а не устройство, особо не вникал, но это несколько иной режим, чем старые 3Г-шки с вирт. ком портами...

Share this post


Link to post
Share on other sites

Может кто-нибудь прокомментировать, что происходит:

 

Посылаем данные

 

TCP CONNECTED
tcp_write(pcb=2000db28, data=20001492, len=178, apiflags=1)
tcp_write: queuelen: 0
tcp_write: queueing 6516:6694
tcp_write: 1 (after enqueued)
tcp_output: snd_wnd 14600, cwnd 4380, wnd 4380, effwnd 178, seq 6516, ack 6516
tcp_output: snd_wnd 14600, cwnd 4380, wnd 4380, effwnd 178, seq 6516, ack 6516, i 0
tcp_output_segment: 6516:6694
pppos_netif_output[0]: proto=0x21, len = 218

И после этого начинается

TCP SEND OK!!!
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 4380, wnd 4380, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 4380, wnd 4380, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 4380, wnd 4380, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb
tcp_slowtmr: rtime 6 pcb->rto 6
tcp_slowtmr: cwnd 1360 ssthresh 2720
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, effwnd 178, seq 6516, ack 6516
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, effwnd 178, seq 6516, ack 6516, i 0
tcp_output_segment: rtseq 6516
tcp_output_segment: 6516:6694
pppos_netif_output[0]: proto=0x21, len = 218
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb
tcp_slowtmr: rtime 12 pcb->rto 12
tcp_slowtmr: cwnd 1360 ssthresh 2720
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, effwnd 178, seq 6516, ack 6516
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, effwnd 178, seq 6516, ack 6516, i 0
tcp_output_segment: rtseq 6516
tcp_output_segment: 6516:6694
pppos_netif_output[0]: proto=0x21, len = 218
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, seg == NULL, ack 6516
tcp_slowtmr: processing active pcb

NO DATA TO RECEIVE
tcp_close: closing in State: ESTABLISHED
tcp_enqueue_flags: queuelen: 1
tcp_enqueue_flags: queueing 6694:6695 (0x1)
tcp_enqueue_flags: 2 (after enqueued)
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, effwnd 178, seq 6694, ack 6516
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, effwnd 178, seq 6694, ack 6516, i 0
tcp_output_segment: 6694:6694
pppos_netif_output[0]: proto=0x21, len = 40

 

Отладка не получила АСК от сервера и пытается периодически что-то на сервер отправить?

 

tcp_output: nothing to send (00000000)
tcp_output: snd_wnd 14600, cwnd 1360, wnd 1360, seg == NULL, ack 6516

 

 

 

Share this post


Link to post
Share on other sites

Проверьте, не отключено ли у вас программное вычисление CRC (CHECKSUM_GEN_xxx, CHECKSUM_CHECK_xxx). В проектах на STM32 его выключают чтобы использовать аппаратное вычисление в MAC, но при работе с модемом данные через MAC не проходят и CRC остается нерасчитанным. А если вы захотите использовать аппаратный расчет для проводного соединения и программный для модема в одной системе - надо использовать LWIP_CHECKSUM_CTRL_PER_NETIF.

Share this post


Link to post
Share on other sites

Спасибо! Программное вычисление CRC включено, в противном случае до сервера вообще бы ничего не доходило, в моем случае доходит 90% посылок, из них 50% с большой задержкой.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this