Берем вариант RAW LWIP 1.4.1 .
Используем :
#define MEM_USE_POOLS 1
#define LWIP_STATS_DISPLAY 1
#define HTTPD_USE_MEM_POOL 1
Нашел картинку в интернете - как работает диспетчер памяти относительно PBUF_POOL :
Первый раз компилируем проект с LWIP 1.4.1, запускаем и сразу при приеме первого пакета udp в pbuf_free получаем LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); , естественно все виснет.
Можно конечно попробовать использовать p->ref >= 0 и даже будет как-то работать. Но это от не понимания кода.
Если отследить цепочки pbuf_alloc ... pbuf_free , то все станет логично и понятно.
Мы же изначально работали так :
frame = pbuf_alloc(PBUF_RAW , recvSize , PBUF_POOL);
ethernet_input(frame, &netif_data);
pbuf_free(frame);
В нашем случае при отработке принятого пакета udp в функции udp_recv_proc зачем-то в конце идет pbuf_free(p). p - это указатель на принятый udp пакет. Таким образом если мы здесь очищаем память (принятого пакета) , то нам далее его очищать не надо!
main() at main.c:362 0x800cf72
usb_polling() at main.c:657 0x800cd4e
ethernet_input() at etharp.c:1 518 0x800be54
ip_input() at ip.c:608 0x80043f2
udp_input() at udp.c:406 0x800af60
udp_recv_proc() at dhserver.c:224 0x80022fe
pbuf_free(pp); // очистка буфера ответа
pbuf_free(p); // очтистка буфера приема
Далее аналогичный затык во втором пакете ARP:
main() at main.c:362 0x800cf72
usb_polling() at main.c:657 0x800cd4e
ethernet_input() at etharp.c:1 529 0x800be88
etharp_arp_input() at etharp.c:933 0x800b898
pbuf_free(p); // очтистка буфера приема
Складывается впечатление , что нам не надо очищать приемный буфер в основном цикле. То есть память мы выделяем сами под принятый пакет, а очищает библиотека LWIP сама.
frame = pbuf_alloc(PBUF_RAW , recvSize , PBUF_POOL);
ethernet_input(frame, &netif_data);
// pbuf_free(frame); не надо!
Далее даже начинается запускаться у нас HTTP сервер. Но все-таки не совсем полноценно, вылетает опять ошибка нехватки памяти. Но это уже проблемы выделения памяти TCP или MEM _256, но не PBUF_MEM. Отслеживается это в версии 1.4.1 через подключение сбора статистики :
И вдруг ловим сообщение , что мы попали в "mem_malloc" . С чего это? Ведь мы должны были уйти от malloc полностью в сторону pbuf_alloc. Срабатывает это после запроса из браузера на адрес 192.168.7.1 (где наш сервер прописался)...
main() at main.c:362 0x800d0e6
usb_polling() at main.c:657 0x800ceca
ethernet_input() at etharp.c:1 518 0x800bfd0
ip_input() at ip.c:614 0x800440e
tcp_input() at tcp_in.c:278 0x80093fc
tcp_listen_input() at tcp_in.c:571 0x800790a
tcp_enqueue_flags() at tcp_out.c:761 0x8009fec
pbuf_alloc() at pbuf.c:350 0x800599e
mem_malloc() at mem.c:81 0x8004f86
В результате в функции tcp_enqueue_flags на ходим такой вызов : pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM), который и вызывает mem_malloc (НЕ memp_malloc )! Выясняется , что надо избавляться от PBUF_RAM .
Тут надо немного разобраться как работает TCP. Зачем ему тут понадобилось выделение памяти и можно ли его заменить другим регионом...