скрытое меню

MEM_LIBC_MALLOC или MEM_USE_POOLS

Вопрос с управлением памятью скрыт за многочисленными макросами. К тому же в LWIP существует не один вариант работы с выделением памяти. Но разобраться в этом надо , так как памяти SRAM 128K контроллеру скорее всего не будет хватать и надо будет что-то разумно урезать , чем-то пожертвовать.

Самая большая проблема в работе не с выделением памяти (выделить ее совсем не сложно), а с очиской ее после использования.

Где резервируется память в LWIP ? Оттуда начинаем изучать исходники.

Есть два подхода к управлению памятью : стандартный MEM_LIBC_MALLOC и через самописный диспетчер памяти MEM_USE_POOLS.

MEM_LIBC_MALLOC это стандартный набор с бибилиотек malloc/free. Его нельзя использовать в многопоточных приложениях от слова совсем.

MEM_USE_POOLS создает пулы (регионы) в памяти для использования под конкретные задачи с добавлением блоков с разной полезной информацией.

memp_std.h

Для начала озадачиваемся наличием трех типов пулов памяти.

 Мы имеем три варианта пулов памяти :
1) LWIP_MEMPOOL 
2) LWIP_MALLOC_MEMPOOL  // pbuf_alloc | pbuf_free [PBUF_RAM]
3) LWIP_PBUF_MEMPOOL - // pbuf_alloc | pbuf_free [PBUF_POOL]

LWIP_MALLOC_MEMPOOL использует pbuf_alloc ( вариант PBUF_RAM) и далее фукцию mem_malloc (см. файл mem.c).

LWIP_PBUF_MEMPOOL вариант использует pbuf_alloc ( вариант PBUF_POOL) и далее фукцию memp_malloc (см. файл memp.c).

Но на самом деле все варианты в итоге используют шаблон LWIP_MEMPOOL.

Одновременно использовать два способа управления памятью MEMP_MEM_MALLOC и MEM_USE_POOLS нельзя!
Если их выставить в 1 оба , то получаем при компиляции #error "MEMP_MEM_MALLOC and MEM_USE_POOLS cannot be enabled at the same time". Это срабатывает защита на уровне компиляции в файле init.c .

По видимому , все области памяти , которые нам будут нужны прописаны в файле memp_std.h . В этом файле видим , что для каждого функционала выделяется отдельный регион памяти. Например для TCP так :

#if LWIP_TCP
LWIP_MEMPOOL(TCP_PCB,        MEMP_NUM_TCP_PCB,         sizeof(struct tcp_pcb),        "TCP_PCB")
LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN,  sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN")
LWIP_MEMPOOL(TCP_SEG,        MEMP_NUM_TCP_SEG,         sizeof(struct tcp_seg),        "TCP_SEG")
#endif /* LWIP_TCP */

LWIP_MEMPOOL это просто шаблон, сам он ничего не делает. Используется в коде по принципу : #define LWIP_MEMPOOL blablabla... и далее #include "lwip/memp_std.h" .

Итак похоже мы поняли , что выбор использования памяти надо делать в пользу MEM_USE_POOLS .

На самом деле MEM_USE_POOLS использует в результате функцию для варианта pbuf_alloc(..,..,PBUF_RAM) mem_malloc и для варианта pbuf_alloc(..,..,PBUF_POOL) функцию memp_malloc для выделения памяти.

Для варианта MEM_USE_POOLS срабатывает напоминание , что нам надо в этом случае включить MEMP_USE_CUSTOM_POOLS.

MEMP_USE_CUSTOM_POOLS

MEMP_USE_CUSTOM_POOLS это регионы MALLOC_ХХХ , которые будет использовать pbuf_alloc (вариант PBUF_RAM). Определяются они в любом файле (у нас lwippools.h) примерно так:

//#ifndef LWIPPOOLS_H - это важно не использовать !!
//#define LWIPPOOLS_H - это важно не использовать !!
LWIP_MALLOC_MEMPOOL_START
LWIP_MALLOC_MEMPOOL(4, 256) 
LWIP_MALLOC_MEMPOOL(2, 512)
LWIP_MALLOC_MEMPOOL(1, 1024) 
LWIP_MALLOC_MEMPOOL_END
//#endif

Похоже есть нюанс - стандартную защиту от повторного включения хэдера *.h надо убрать.

Дефайн LWIP_MALLOC_MEMPOOL(num, size) это макрос :
LWIP_MEMPOOL(POOL_##size, num, (size + sizeof(struct memp_malloc_helper)), "MALLOC_"#size)
LWIP_MEMPOOL просто резервирует память как и для других регионов памяти.

Если прочитать всю таблицу распределения памяти , то она выглядит примерно так :

00 size x001C num 0004   next:20000728  RAW_PCB 
01 size x0020 num 0004   next:200007A0  UDP_PCB 
02 size x0098 num 0005   next:200009A8  TCP_PCB 
03 size x001C num 0008   next:20000B80  TCP_PCB_LISTEN 
04 size x0014 num 0016   next:20000CD0  TCP_SEG 
05 size x0020 num 0005   next:20000D58  REASSDATA 
06 size x0018 num 0015   next:20000ED0  FRAG_PBUF 
07 size x0014 num 0003   next:20000F14  SYS_TIMEOUT 
08 size x0010 num 0016   next:2000101C  PBUF_REF/ROM 
09 size x05FC num 0016   next:20006404  PBUF_POOL 
10 size x0104 num 0006   next:2000740C  MALLOC_256 // 10 = MEMP_POOL_HELPER_FIRST !
11 size x0204 num 0002   next:20007614  MALLOC_512 
12 size x05EC num 0002   next:20007A1C  MALLOC_1512 // 12 = MEMP_POOL_HELPER_LAST !

У каждого региона (к счастью) есть символьное название. Мы можем подключить сбор статистики и выводить на экран в любой момент текущее состояние расхода памяти каждого региона:

avail: 04 used: 00 max: 00 err: 00  [RAW_PCB]
avail: 04 used: 02 max: 02 err: 00  [UDP_PCB]
avail: 05 used: 00 max: 01 err: 00  [TCP_PCB]
avail: 08 used: 01 max: 01 err: 00  [TCP_PCB_LISTEN]
avail: 16 used: 00 max: 00 err: 00  [TCP_SEG]
avail: 05 used: 00 max: 00 err: 00  [REASSDATA]
avail: 15 used: 00 max: 00 err: 00  [FRAG_PBUF]
avail: 03 used: 02 max: 02 err: 00  [SYS_TIMEOUT]
avail: 16 used: 00 max: 00 err: 00  [PBUF_REF/ROM]
avail: 16 used: 01 max: 02 err: 00  [PBUF_POOL]
avail: 06 used: 00 max: 00 err: 00  [MALLOC_256]
avail: 02 used: 00 max: 00 err: 00  [MALLOC_512]
avail: 02 used: 00 max: 00 err: 00  [MALLOC_1512]

Дефайны , которые влияют на расход памяти :

TCP_MSS: TCP Maximum segment size

TCP_MSS: TCP Maximum segment size