скрытое меню

регионы памяти

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

Хорошая картинка нашлась в интернете :

фотка 1

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).