pbuf_free

Берем вариант RAW LWIP 1.4.1 .

Используем :
#define MEM_USE_POOLS 1
#define LWIP_STATS_DISPLAY 1
#define HTTPD_USE_MEM_POOL 1

Нашел картинку в интернете - как работает диспетчер памяти относительно PBUF_POOL :

фотка 1

Первый раз компилируем проект с 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. Зачем ему тут понадобилось выделение памяти и можно ли его заменить другим регионом...