Здесь мы Не рассматриваем динамическое выделение памяти типа malloc из закрытых стандартных библиотек.
Поэтому в ld файле _Min_Heap_Size = 0x0000. И все прекрасно рабротает.
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x0000; /* required amount of heap */
_Min_Stack_Size = 0x4000; /* required amount of stack */
Здесь рассматривается только работа с памятью из разных регионов , которые создаются на этапе компиляции, то есть их размер заранее фиксируется.
Память из таких регионов обычно выделяется через функцию pbuf_alloc и освобождается через pbuf_free .
В качестве параметра в pbuf_alloc передается тип памяти , которую мы хотим использовать. Типов несколько :
PBUF_POOL
PBUF_RAM
PBUF_ROM
PBUF_REF
(тип PBUF_POOL не путайте тут с одноименным названием одного из регионов)
Хорошая картинка нашлась в интернете :
PBUF_POOL
Сюда мы помещаем все приходящие из сети пакеты (сегменты). Размер блока вмещает максимальный размер пакета в сети Ethernet 1540.
p = ( struct pbuf * ) memp_malloc( MEMP_PBUF_POOL );
Что это за загадочный параметр MEMP_PBUF_POOL ? Это просто номер региона памяти. Найти ссылки по коду на него нельзя, так как появляется он на основе включения в код такого макроса:
LWIP_PBUF_MEMPOOL(PBUF_POOL , PBUF_POOL_SIZE, PBUF_POOL_BUFSIZE, "PBUF_POOL")
PBUF_RAM
А этот вариант выделения памяти (PBUF_RAM) используется в основном для ответов.
Это вариант выделения из общей кучи. Но куча может быть реализована и без всяких malloc , а по типу региона памяти PBUF_POOL , то есть кучей будет зарезервированные регионы памяти [MALLOC_256] , [MALLOC_512] , [MALLOC_1512] . В этих регионах памяти за выделение и освобождение отвечаете только вы.
p = ( struct pbuf* ) mem_malloc (LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE( length ) );
Тут в отличии от PBUF_POOL вроде бы вызывается не memp_malloc , а mem_malloc , но по факту далее вызывается именно memp_malloc и выделит память из региона [MALLOC_XXX]:
16564 : ------------------------ > pbuf_alloc
16565 : layer=[PBUF_TRANSPORT] offset=54 type=[PBUF_RAM]
16565 : ---------------------------- > mem_malloc
16565 : required_size=80
16565 : -------------------------------- > memp_malloc_fn
16566 : ------------------------------------ > memp_overflow_check_all
16566 : ------------------------------------ < memp_overflow_check_all
16566 : memp:2000B13C memp_sizes[MALLOC_256] size=260
16567 : -------------------------------- < memp_malloc_fn
16567 : pbuf:2000B154
16567 : ---------------------------- < mem_malloc
16567 : ------------------------ < pbuf_alloc
PBUF_ROM и PBUF_REF
PBUF_ROM или PBUF_REF это одно и то же. Это неизменяемая память (FLASH контроллера ). Тут например хранится контент страниц нашего сайта , картинка favicon.ico , файл zepto.min.js и т.д. Все это представлено в виде массивов на языке С ( смотрите файл fsdata.c).
p = ( struct pbuf * ) memp_malloc( MEMP_PBUF );
Что это за номер региона памяти MEMP_PBUF ? Это опять же один из наших наш регионов [MALLOC_xxx]. Смотрите макрос :
LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM")
MEMP_ добавляйте с первому параметру в LWIP_PBUF_MEMPOOL и получите номер этого региона.
PBUF_REF/ROM - это мы задаем символьное название региона. В результате будет занесено в массив memp_desc.
У вас может возникнуть вопрос как же мы будем формировать пакет ответа если данные неизменяемые ? Правильно к [PBUF_REF/ROM] еще выделяются связанные блоки памяти из других регионов. Например для отправки TCP сегмента из региона памяти обычно [MALLOC_XXX] происходит выделение и еще из региона [TCP_SEG]. То есть формируется цепочка со связями :
[TCP_SEG]
[MALLOC_XXX]
[PBUF_REF/ROM]
Полезные фичи по сбору информации и регионах
Чтобы понять ,что происходит с памятью делаем простую функцию сбора статистики на основе массива memp_pools (здесь определены все зарезервированные регионы памяти) и тупо наблюдаем за расходом памяти. Что-то в этом роде :
void memp_pools_stat()
{
DEBUG_ETH ( LEFT , ("----------------------------\n"));
for(uint32_t ii=0; ii < MEMP_MAX ; ii++)
{
printf("%.2d size x%.4X num %.4d used %.4d avail %.4d err %.4d base:x%.8X tab:x%.8X *tab:x%.8X **tab:x%.8X %s\n",
ii,
memp_pools[ii]->size ,
memp_pools[ii]->num , memp_pools[ii]->stats->used,
memp_pools[ii]->stats->avail, memp_pools[ii]->stats->err ,
memp_pools[ii]->base, memp_pools[ii]->tab,
*(struct memp *)memp_pools[ii]->tab , **(struct memp **)memp_pools[ii]->tab ,
memp_pools[ii]->desc);//
}
DEBUG_ETH ( LEFT , ("----------------------------\n"));
}
Таблица расхода памяти
12102 : ----------------------------
00 size x001C num 0004 used 0000 avail 0004 err 0000 base:x2000A388 tab:x20001488 *tab:x2000A3DC **tab:x2000A3C0 RAW_PCB
01 size x0020 num 0004 used 0001 avail 0004 err 0000 base:x2000D524 tab:x2000149C *tab:x2000D564 **tab:x2000D544 UDP_PCB
02 size x00B0 num 0005 used 0000 avail 0005 err 0000 base:x2000D5A8 tab:x20001490 *tab:x2000D868 **tab:x2000D7B8 TCP_PCB
03 size x001C num 0008 used 0000 avail 0008 err 0000 base:x2000CF94 tab:x20001494 *tab:x2000D058 **tab:x2000D03C TCP_PCB_LISTEN
04 size x0014 num 0040 used 0000 avail 0040 err 0000 base:x2000A3FC tab:x20001498 *tab:x2000A708 **tab:x2000A6F4 TCP_SEG
05 size x002C num 0005 used 0000 avail 0005 err 0000 base:x2000A2A8 tab:x2000146C *tab:x2000A358 **tab:x2000A32C ALTCP_PCB
06 size x0020 num 0005 used 0000 avail 0005 err 0000 base:x2000D078 tab:x2000148C *tab:x2000D0F8 **tab:x2000D0D8 REASSDATA
07 size x0018 num 0015 used 0000 avail 0015 err 0000 base:x2000CD24 tab:x20001470 *tab:x2000CE74 **tab:x73773E73 FRAG_PBUF
08 size x0010 num 0016 used 0000 avail 0016 err 0000 base:x2000CE90 tab:x20001474 *tab:x2000CF80 **tab:x2000CF70 PBUF_REF/ROM
09 size x0260 num 0016 used 0015 avail 0016 err 0001 base:x2000A720 tab:x20001478 *tab:x2000A720 **tab:x00000000 PBUF_POOL
10 size x0104 num 0004 used 0000 avail 0004 err 0000 base:x20009E94 tab:x20001480 *tab:x2000A1A0 **tab:x2000A09C MALLOC_256
11 size x0204 num 0002 used 0000 avail 0002 err 0000 base:x20009A88 tab:x20001484 *tab:x20009C8C **tab:x20009A88 MALLOC_512
12 size x0404 num 0001 used 0000 avail 0001 err 0000 base:x2000D11C tab:x2000147C *tab:x2000D11C **tab:x00000000 MALLOC_1024
12102 : ----------------------------
Например у нас увеличивается расход PBUF_POOL , доходит до максимального (0015) и все виснет . По-видимому не освобождается своевременно память. Для информации : мы мучаем вариант с FreeRTOS (static) и LWIP RAW (именно RAW).
По таблице расхода памяти : для UDP_PCB used 0001 означает ,что мы добавили прослушку одного порта (у нас 67 dhcp). Далее приходящие пакеты добавляют, убирают used в PBUF_POOL... Но в результате все-равно возникаем переполнение (00015).