Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: lwIP (PPP) проблема
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > FreeRTOS
kan35
Модем Quectel M72, FreeRTOS 7 на sm32.
Работаем через PPP протокол и сверху TCP/IP по виалоновскому протоколу.
При приемо-передаче небольших пакетов данных проблем не возникает. Но при передаче на устройство большого массива байтов прием сбоит. Стек принимает ровно 9 IP пакетов (по ~1400байт каждый), после чего netconn_recv перестает принимать пакеты (потому что модем их перестает выдавать). Память нигде не утекает, это контроллируется. На нехватку памяти не похоже. FreeRTOS находится в IDLE >92% времени. Такое ощущение что проблема на уровне IP, перешевелил все настроки, которые понимал и не понимал, но бесполезно - 9 пакетов и хоть умри. Тип и содержание файла не влияет на результат.
Из зависания выходит если начать новую передачу на устройство. При этом в лог сыпется такое:
Код
pppInProc[0]: got 1355 bytes
[b]pppInProc[0]: Dropping bad fcs 0x63B8 proto=0x0021[/b]
pppDrop: pbuf len=500
pppInProc[0]: got 1405 bytes
pppInput[0]: ip in pbuf len=492
pppifOutput[0]: proto=0x0021
pppInProc[0]: got 1405 bytes
pppInput[0]: ip in pbuf len=492
pppifOutput[0]: proto=0x0021

Тут видно, что начинается передача которая подвисла, но срывается FCS (но потом восстанавливается) и в конечном итоге, когда массив допередастся, система вновь приходит в штатное состояние.

Подскажите где могла собака порыться? Чую что какие то настройки надо подправить в lwipopt.h, но допетрить не могу. Спасибо!!!!!
kan35
Заменил модем на SIM300DZ - результат на 100% тот же самый
Скачал заново версию стека 1.3.2, полностью обновил все файлы стека в своем проекте, опять безрезультатно.
вывод - проблема точно в стеке или в его настройке.

Файл с пользовательскими настройками lwipopt.h прилагаю, прошу поделиться аналогичным файлом, если у вас описанная проблема не наблюдается.

А вот так выглядят функции приема/передачи по последовательному каналу в sio.c

Код
volatile unsigned char stop = 0;
extern xQueueHandle queue_gprs_bytes;

u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len)
{
    unsigned long i = 0;
    while (xQueueReceive(queue_gprs_bytes, &data[i], 0) == pdTRUE )
    {
        i++;
        if (stop || (i == len) )
        {
            stop = 0;
            return i;
        }
    }
    return i;
}

u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len)
{
    for (unsigned long i = 0; i<len; i++)
    {
        while (    !USART_GetFlagStatus(USART_MODEM, USART_FLAG_TXE) );
        USART_SendData(USART_MODEM, data[i]);
    }
    return len;
}

void sio_read_abort(sio_fd_t fd)
{
    stop = 1;
}
cpl
Какой менеджер памяти в freertos используете ? сколько памяти под кучу ?
Сколько памяти выделено для стека ?
Попробуйте включить полное протоколирывание, а так непонятно что не так.
kan35
Цитата(cpl @ Oct 27 2011, 22:28) *
Какой менеджер памяти в freertos используете ? сколько памяти под кучу ?
Сколько памяти выделено для стека ?
Попробуйте включить полное протоколирывание, а так непонятно что не так.

Использую heap_2, и в lwIP используется только куча freeRTOS, памяти выделил около 50кБ, стеку хватает, так как в ином случае последний бы ругался в лог и к тому же принимая в цикле данные pbuf = netconn_recv вижу, что используются одни и те же сегменты pbuf - и паять не утекает. И еще - увеличение или уменьшение кучи не приводит ник чему - 9 пакетов и стопорится. Хотя изредка 1 на 100 случаев принимается от 10 до 13 пакетов.
Подключался в разных местах - размеры пакетов у разных операторов в разных точках немного отличались - от 1260 до 1460 байт, но результат один - 9 пакетов:-)
Модемы тоже менял - без изменений!

Код
    struct netbuf * in_buf;
    unsigned short k = 2;
    while (bytesleft)
    {
        if (in_buf = netconn_recv(conn))
        {
            // успешно приняли что то
            char * incoming_data;
            unsigned long buflen = netbuf_len(in_buf);

            if (incoming_data = (char *)pvPortMalloc(buflen))
            {
                {
                    char * data; u16_t len;
                    netbuf_data(in_buf, (void **)&data, &len);
                    printf_diagn("%d: %lX->%lX (%d:%d)\r\n\r\n", k, data, incoming_data, buflen, bytesleft-buflen );
                }
                netbuf_copy(in_buf, incoming_data, buflen);
                //file_write(file, buflen, (unsigned char *)incoming_data);
                vPortFree(incoming_data);
            }
            bytesleft -= buflen;
            netbuf_delete(in_buf);
            k++;
        }
        else
            bytesleft = 0;
    }

lwipopts.h
sio.c

Порт sys_arch.c lwIP для FreeRTOS взял из примера ST для STM32F2xx.
Больше ничего в стеке я не менял! И потому хотел поинтересоваться - получалось ли у вас принимать такие передачи в стеке lwIP и в частности через их PPP?

Вот логи:
TCP log: TCP+.txt
IP log: IP.TXT
PPP log: PPP.txt
Сняты с разных подключений, но все остановлены на месте где модем перестает выдавать очередной пакет - всегда после 9 пакета.
cpl
CTS-RTS модема обрабатываются корректно ?
Попробуйте посмотреть не влетает ли ртос в функцию FREERTOS:vApplicationMallocFailedHook.
kan35
Цитата(cpl @ Oct 31 2011, 00:13) *
CTS-RTS модема обрабатываются корректно ?
Попробуйте посмотреть не влетает ли ртос в функцию FREERTOS:vApplicationMallocFailedHook.

У меня между модемом и контроллером только RX и TX. У модема эти сигналы висят в воздухе. В режиме связи конкретный модем QUECTEL L72 использует XON XOFF и стек это поддерживает.
cpl
Где в стеке поддержка XON XOFF, в lwip1.3.2 не нашел ?
Работу XON XOFF проверяли ?
Смотреть пробовали когда выдает pppInProc[0]: Dropping bad fcs 0x63B8 proto=0x0021
что выкинул модем и что действительно было принято контролером.
Попробуйте посмотреть не влетает ли ртос в функцию FREERTOS:vApplicationMallocFailedHook.
Если IP_REASSEMBLY=1 ?
если убрать (char *)pvPortMalloc(buflen) будет ли затык ?
kan35
Цитата(cpl @ Nov 1 2011, 00:02) *
Где в стеке поддержка XON XOFF, в lwip1.3.2 не нашел ?
Работу XON XOFF проверяли ?

cpl, спасибо большое тебе
Оказалось следующее: модем действительно работал через аппаратные CTS и RTS, хотя при согласовании параметров выдавал поддержку XON/XOFF:
Код
...
ppp_send_config[0]: outACCM=0 0 A 0
ppp_recv_config[0]: inACCM=0 0 A 0
link_established: 0
upap_lowerup: 0 s=0
IPCP: lowerup state 0 (LS_INITIAL) -> 2 (LS_CLOSED)
upap_authwithpeer: 0 user=beeline password=beeline s=1
...

Возможно, я не правильно это понимаю (0 0 A 0)?

Достаточно было подать AT команду
AT+IFC=1,1 и XON XOFF действительно заработали, а по поддержке стеком, сейчас изучаю, думал что поддерживает...
kan35
Рано обрадовался. Началось совершенно непонятное.
IFC=1,1 конечно было не лишним, но как оказалось XON и XOFF - 0x11 и 0x13 в пакетах так и не начали участвовать, это значит что RX буферы модема вполне все вмещают. Мои dropped были из за того, что в контроллере переполнялся messagebox, я увеличил его и все стало гладко. Пришлось вручную добавить поддержку XON XOFF в свой драйвер, это оказалось не сложным делом.
Однако, образовалось новое ограничение - 35 пакетов и остановка.
Я первым делом взял старые резервные копии и опробовал - и почему то не удивился, на них тот же самый результат - 35 пакетов! стабильно, четко...
вот моя инициализация модема:
ATV1
AT+CLIP=1
AT+CRC=0
AT+IFC=1,1
AT+CGDCONT=1,"IP","internet.beeline.ru"
ATD*99***1#\r
... и поехал PPP

на что думать?
cpl
XON-XOFF Не применял, пока обхожусь CTS-RTS.
Стек об XON-XOFF нечего не знает, это больще относится к SIO.

Цитата(kan35 @ Nov 2 2011, 11:46) *
Однако, образовалось новое ограничение - 35 пакетов и остановка.

Что значит остановка ?

kan35
Цитата(cpl @ Nov 2 2011, 13:37) *
XON-XOFF Не применял, пока обхожусь CTS-RTS.
Стек об XON-XOFF нечего не знает, это больще относится к SIO.


Что значит остановка ?

Я в SIO и добавил отслеживание XON XOFF. Попробую аппаратно прокинуть еще и RTS, CTS.

Остановка это значит, что контроллер отправил подтверждение приема очередного пакета (№35) ~1400байт и все, модем не выдает следующий пакет. Как только по таймауту выходит из netconn_recv прога начинает предпринимать попытки ожить - отправляет данные, пытается принять подтверждения, и в это время с подтверждениями сыпятся все те пакеты, которые не дошли! все сыпется кучей, как только пакеты заканчиваются, прога оживает полноценно (до следующей попытки принять большой массив).

При чем что характерно, каждая новая порция данных - это всегда ровно 35 пакетов. Потом опять торможение до нового netconn_write, после него опять 35... И до ни прога ни стек не падают мертво - весгда все очухивается и продолжает трудиться, я уже в отчаянии. Почему вдруг стало вместо 9 35, при чем и в старых проектах и на других платах и с разными операторами...
cpl
Система не упала и ошибок не выдает значит все нормально работает.
Может GPRS тормозить, кто знает что там у оператора твориться, бываю таймауты по несколько десятков секунд пока прейдет новая порция данных.
Сколько по времени продолжается это самая остановка ?
Если попробовать только принимать пакеты и соответственно на передающей стороне только передавать в непрерывном режиме, посмотреть что изменится ?
Какой алгоритм обмена данными ?
Почему длинна пакетов приближена к максимально возможной ?
kan35
GPRS не тормозит на самом деле, а стоит только отправить пакет с данными - модем начинает валить следующие 35 пакетов, потом опять подвисает и т д
Оператора менял, модем менял, возвращался к старым прошивкам - которые работали на 9 пакетов - они стали тоже по 35 пакетов принимать. Мистика!!!
Пакеты нарезаются по 1400 байтов у билайна, у мегафона по 1300, я это не регулирую вроде.
Остановка продолжается 60 секунд - ровно тот таймаут на netconn_recv. Потом я начинаю передачу и модем оживает.
Скажу прямо, я соединяюсь с сервером Wialon по их протоколу Wialon IPS. Функция, которую я отлаживаю - обновление прошивки, которая заключается в отправке файла на подсоединенное устройство - даже без подтверждений - бинарник тупо выплёвывается в устройство. Уже грешу на какое то нестандартное поведение сервера. Хотя если через гипертерминал я соединяюсь с сервером, то массив массив данных передается в гипертерминал четко за доли секунды.

Я бы не отказался от файла lwipopt.h с рабочей системы lwip-1.3.2.
cpl
Цитата(kan35 @ Nov 2 2011, 22:38) *
Я бы не отказался от файла lwipopt.h с рабочей системы lwip-1.3.2.

Держите.
kan35
Цитата(cpl @ Nov 3 2011, 00:24) *
Держите.

ну что собственно, не помогло как ни странно:-)
Правда чтобы заработало я добавил:
Код
#define LWIP_SOCKET    0
#define LWIP_ARP    0
#define lwipINTERFACE_STACK_SIZE        1000
#define lwipINTERFACE_TASK_PRIORITY        1
#define LWIP_SO_RCVTIMEO                1// это пробовал и 0 и 1

Но TCP_MSS явно на что то влияет, так как при значении 600 я принимаю четко 75 пакетов. Уменьшил TCP_MSS до 100 - начал принимать 175 пакетов. Может быть проблема кроется в FreeRTOS, у вас какая версия? (у меня 7.0.0).
cpl
Цитата(kan35 @ Nov 3 2011, 10:08) *
у вас какая версия? (у меня 7.0.0).


6.0.3
kan35
Цитата(cpl @ Nov 3 2011, 11:38) *
6.0.3

а большие пакеты принимать пробовали?
скажем, от 100кб
cpl
Цитата(kan35 @ Nov 3 2011, 16:14) *
а большие пакеты принимать пробовали?
скажем, от 100кб


Пакет 100кб ?!

Расматриваю приходящие даные как поток с последующей разборкой того что пришло.
Для теста всял большой текстовый файл 250кб и отправил с сервера через инет клиенту (своей железке)
минут 5 может больше приходили данные неприрывно, пока все не пришло, система живет.

У Вас значение TCP_MSS = 1500-40, зачем такое значение ?
и почему ?
Какой у Вас размер буфера для принятых данных из модема ?
kan35
Я начал работать на аппноте от ST - там был ethernet и это (1500-40) - максимальный пакет для eth. В принципе, в PPP получается примерно такой же размер - 1260-1460 байт и я его не стал менять. Я пробовал уменьшать до 600 и до 100 байт как я писал в одном из прошлых сообщений- - результат отрицательный.
Буфер приема (PBUF) - 5кБ:
#define PBUF_POOL_SIZE 10
#define PBUF_POOL_BUFSIZE 500
Пробовал увеличивать - не влияет.
Исходники на lwIP скачал с их сайта, и полностью файлы в проекте заменил, чтобы не было шанса что я что то не то сделал...
FreeRTOS обновил до 7.0.2 на всякий случай.
Еще не понятно почему раньше было 9 пакетов - теперь 35... Хотя ничего не изменилось.
cpl
Цитата(kan35 @ Nov 3 2011, 17:11) *
Еще не понятно почему раньше было 9 пакетов - теперь 35... Хотя ничего не изменилось.


Раньше были проблемы с FlowControl, или не всчет !?

Цитата
Какой у Вас размер буфера для принятых данных из модема ?

Подругому: Какой размер очереди queue_gprs_bytes ?

Код
#define TCPIP_THREAD_PRIO             (tskIDLE_PRIORITY)
#define PPP_THREAD_PRIO        (tskIDLE_PRIORITY)


По приоритетам, не маловато ли ?


kan35
нет, с FlowControl нет проблем и не было (просто тогда было совпадение).
queue_gprs_bytes сейчас 2000 байт, когда было 200 байт - то иногда не успевал обрабатывать и получались dropped.
Приоритетами играл - не то.

Вот еще что, я немного переделал функцию приема и вот что получилось:
Код
void get_rest_of_FW(unsigned long bytesleft, File * file)
{
    LED_RedBlink(10);
    struct netbuf * in_buf;
    unsigned short k = 2;
    while (bytesleft)
    {
        if (in_buf = netconn_recv(conn))
        {
            // успешно приняли что то
            char * incoming_data;
            unsigned long buflen = netbuf_len(in_buf);
            if (incoming_data = (char *)pvPortMalloc(buflen))
            {
                {
                    char * data; u16_t len;
                    netbuf_data(in_buf, (void **)&data, &len);
                    printf_diagn("%d: %lX->%lX (%d:%d)\r\n\r\n", k, data, incoming_data, buflen, bytesleft-buflen );
                }
                netbuf_copy(in_buf, incoming_data, buflen);
                if ( ((signed long)bytesleft - (signed long)buflen) < 0 ) //// заплатка
                    buflen = bytesleft;
                file_write(file, buflen, (unsigned char *)incoming_data);
                vPortFree(incoming_data);
            }
            else
            {
                LED_RedBlink(4);
            }

            bytesleft -= buflen;
            netbuf_delete(in_buf);
            k++;
        }
        else
        {
            //bytesleft = 0;
            netconn_write(conn, "#M#push\r\n", strlen("#M#push\r\n"), NETCONN_NOCOPY); // заплатка
        }
    }
    LED_RedBlink(0);
}

Здесь собственно что: когда данные из модема перестают поступать я кидаю строчку "#M#push\r\n" в сервер (это типа просто текстовое сообщение от клиента), после этого сервер начинает опять слать очередную порцию данных. И так соответственно 2 раза за 130кБ.
В конце массива я на 2 своих текстовых сообщения получаю 2 текстовых ответа-подтверждения (в рамках протокола Wialon). Просто не беру эти куски в учет и все... - файл передан.
В этой связи вопрос такой: может ли быть на сервере или у оператора gsm какое то ограничение на время отправки пакета с таким вот эффектом запора?
kan35
Проблема решена, оказывается дело не в стеке и даже не в моем софте, а в сервере Wialon который почему то вот так дробил пакеты и зависал. После 2-недельного обвинений меня в том, что у меня кривые руки виалоновские инженеры все таки поправили баг и стало мне счастье.
cpl
Примите мои искрение поздравления.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.