Перейти к содержанию
    

STM32F4 + FreeRTOS + lwip + pppos + usb modem

Добрый день!

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

 

Изменено пользователем Алексей ВМ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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. А вот куда дальше копать - пока в затруднении

Изменено пользователем Алексей ВМ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

 

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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;
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Изменено пользователем Алексей ВМ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Алексей ВМ сказал:

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

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

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...