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

FreeRTOS + lwIP

Добрый день!

Имеются FreeRTOS 8 + lwIP 1.4.1 + LPC2478.

Столкнулся с такой проблемой. Работаю через Netconn API. Шлю на плату TCP пакеты (утилитой netcat передаю файлы по X Мб). Какое-то время пакеты проходят через стек нормально (10...20...40 Мб). Но в какой-то момент времени стек все чаще и чаще начинает выдавать отказ в выделении памяти под принятый пакет (memp_malloc_fn), пока прием совсем не "захлебывается". При этом передача от платы через другое соединение работает нормально. Принятые пакеты netconn_recv не обрабатываю, а просто отбрасываю (пока), затем удаляю буфер netbuf_delete. Стеки, кучи операционки большие и пустые. В lwipopts.h тоже памяти выделено достаточно. Стек по какой-то причине выделяет больше пулов, чем освобождает. Причину утечки никак найти не могу. На вход стека с mac пакеты выдаю корректные (по крайней мере так думаю).

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

 

ethernetif.zip

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


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

На заступ надо провериться -- вдруг данных пишется больше, чем ожидалось (или железо пинается не на те адреса, выгрузка "в молоко"), портятся системные области, а там уже и "рух" недалеко.

Если нет такого "системного" средства в ОС, надо как-то "встрять" в каждое выделение/освобождение памяти, выделять на 16 байт больше, заливать первые 8 чем-то "особым", типа "DEADBEAF", последние 8 аналогично и возвращать указатель +8, ну а при возврате -- проверять на "особость". Обычно "вдаль" сразу никто не заступает, и так ловится большинство проблем.

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

Тогда нужно стабилизировать наступление глюка: например, "принимать" пакеты не из физики, а из рандомного генератора. Вдруг при его стабильном стартовом значении и дальше всё будет повторяться 1в1...

 

Исходники если есть -- при первом же неуспехе memp_malloc_fn можно ставить точку останова, прыгать там на повторный вызов и разглядывать по шагам, отчего же не вышло. Вдруг ОС не будет "в фоне" бяки делать в процессе этого.

 

Реентерабельность вдруг где хромает, семафор где-то "застреливают" аппаратной выгрузкой, возвращаемое значение при захвате не анализируют полностью...

 

Абсолютно детерминированная "повторябельность на N-м такте" при лечении глюков может сильно помочь, её надо добиваться в первую очередь. Тогда, в принципе, можно остановиться на любом предыдущем и проследить всё остальное. Где-то и "назад" могут степать отладчики, но жить в эту пору прекрасную... ;)

 

Передачу "из" тоже можно задействовать в крайнем случае -- в те пакеты писать трассировку выделений/освобождений адресов, она не должна сильно изменить "приёмное" направление, чтобы глюк совсем исчез, но позволит на персоналке потом декодировать и проводить анализы нелогичностей, добавлять новую трассировку в целях отладки...

 

То, что обрасывается, тоже можно проверять "на подлинность" -- слалось такое вообще снаружи, или мусор.

Тело выделяемого пакета при такой проверке тоже должно иметь детерминированную заливку, чтобы не было "повторного использования" принятых 3 мин назад данных как "более-менее валидных".

 

TCP в данном случае достаточно нехороший протокол (там много форматных излишеств ради восстановления пропавших пакетов, которые в локалке очень трудно сейчас "задушить"), легче через UDP попытаться вести "обстрел".

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


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

На заступ надо провериться -- вдруг данных пишется больше, чем ожидалось (или железо пинается не на те адреса, выгрузка "в молоко"), портятся системные области, а там уже и "рух" недалеко.

Если нет такого "системного" средства в ОС, надо как-то "встрять" в каждое выделение/освобождение памяти, выделять на 16 байт больше, заливать первые 8 чем-то "особым", типа "DEADBEAF", последние 8 аналогично и возвращать указатель +8, ну а при возврате -- проверять на "особость". Обычно "вдаль" сразу никто не заступает, и так ловится большинство проблем.

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

Тогда нужно стабилизировать наступление глюка: например, "принимать" пакеты не из физики, а из рандомного генератора. Вдруг при его стабильном стартовом значении и дальше всё будет повторяться 1в1...

 

Исходники если есть -- при первом же неуспехе memp_malloc_fn можно ставить точку останова, прыгать там на повторный вызов и разглядывать по шагам, отчего же не вышло. Вдруг ОС не будет "в фоне" бяки делать в процессе этого.

 

Реентерабельность вдруг где хромает, семафор где-то "застреливают" аппаратной выгрузкой, возвращаемое значение при захвате не анализируют полностью...

 

Абсолютно детерминированная "повторябельность на N-м такте" при лечении глюков может сильно помочь, её надо добиваться в первую очередь. Тогда, в принципе, можно остановиться на любом предыдущем и проследить всё остальное. Где-то и "назад" могут степать отладчики, но жить в эту пору прекрасную... ;)

 

Передачу "из" тоже можно задействовать в крайнем случае -- в те пакеты писать трассировку выделений/освобождений адресов, она не должна сильно изменить "приёмное" направление, чтобы глюк совсем исчез, но позволит на персоналке потом декодировать и проводить анализы нелогичностей, добавлять новую трассировку в целях отладки...

 

То, что обрасывается, тоже можно проверять "на подлинность" -- слалось такое вообще снаружи, или мусор.

Тело выделяемого пакета при такой проверке тоже должно иметь детерминированную заливку, чтобы не было "повторного использования" принятых 3 мин назад данных как "более-менее валидных".

 

TCP в данном случае достаточно нехороший протокол (там много форматных излишеств ради восстановления пропавших пакетов, которые в локалке очень трудно сейчас "задушить"), легче через UDP попытаться вести "обстрел".

 

Я кое-что из предложенного уже перепробовал. И точки останова ставил, и собирал статистику выделений-освобождений и т.д. и т.п. Не догадался подсовывать на вход стека сгенерированные данные. Повторяемости нет. С длинами пакетов все нормально, с семафорами, критическими секциями тоже все в порядке. Трудность в том, что что-то ломается значительно раньше, чем это уже проявляется.

 

Пока остановился на том, что полноценный стек для моей задачи не нужен (просто хотелось его пощупать). Время, которое я мог себе позволить на решение этой проблемы, закончилось.

Сейчас уже проще самому написать простейшую реализацию UDP, чем сейчас и занялся. А с потерей пакетов разбираться буду уже на прикладном уровне.

Дальше планирую работать с кортексами, а там есть уже готовые связки (почти официальные, только до ума довести, под себя подстроить) стека, ОС (например в LPCExpresso). Возможно там такой проблемы уже не будет.

Но вообще разобраться было бы интересно. При случае кое-что из предложенного попробую. Спасибо.

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


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

Память выделяется с помощью pvPortMalloc?

 

На сколько я понял, то LwIP имеет свой механизм выделения памяти. При беглом просмотре он потокобезопасен.

 

В том варианте, в каком я использую стек, он выделяет память единожды, а потом выделяет/освобождает пулы под/от данные, не пользуясь функциями типа malloc. Я в этот механизм не вмешиваюсь. У меня получается, что заканчиваются свободные пулы при p = pbuf_alloc( PBUF_RAW, len, PBUF_POOL ) (и дальше по цепочке до memp_malloc_fn).

 

Но пробовал и другие варианты, результат аналогичен.

 

Мне кажется, что проблема явно не в самом стеке, а в его порте (emac.c, ethernetif.c) или я что-то не правильно настроил в lwipopts.h

 

 

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


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

На сколько я понял, то LwIP имеет свой механизм выделения памяти.

В общем да, но зависит от.

На всякий случай можно перепроверить константы MEM_* и MEMP_*

lwip\src\include\lwip\opt.h

lwipopts.h

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


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

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

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

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

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

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

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

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

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

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