|
|
  |
FreeRTOS Heap_x.c |
|
|
|
Oct 17 2008, 19:14
|

Местный
  
Группа: Свой
Сообщений: 331
Регистрация: 22-07-08
Из: Р О С С И Я
Пользователь №: 39 145

|
Цитата(sergeeff @ Oct 7 2008, 16:18)  Тестировал 2.4.2. Включил в свой проект и погонял свое устройство день. Все работало, как и с прежним аллокатором BGET (тоже известная вещь), т.е. никаких проблем замечено не было. Подключил я этот алокатор. Вылетает в dabort_hamdler при входе в макрос EXTRACT_BLOCK_HDR(b, tlsf, fl, sl); Использую CW. Может уже разбирались с этой проблемой?
|
|
|
|
|
Oct 17 2008, 21:29
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(sergeeff @ Oct 7 2008, 18:46)  И излишества всякие, нехорошие ... Думал просто oткомментировать немного и выложить heap manager для FreeRTOS, но получается, что сначала нужно описывать почему он сделан именно так  . Попробую: 1. Хотелось иметь возможность получения списков свободных и занятых блоков памяти во время консольной отладки. 2. Хотелось иметь признак для чего блок памяти используется системой (TCB/Stack, Очередь,...) 3. Хотелось иметь возможность знать какая задача породила тот или иной блок - самое простое, при запросе блока сохранять адрес TCB. 4. Обязательна возможность использовать с менеджером разрозненные блоки памяти в едином списке. И наоборот - использовать несколько независимо управляемых блоков памяти (например, если эти блоки памяти имеют разное назначение/свойства, или для ручной борьбы с дефрагментацией ) 5. Особые навороты с для ускорения поиска свободных блоков типа "испанского варианта" не нужны, поскольку - основная масса блоков памяти под задачи, очереди и прочее выделяется "навсегда" и естественно выделение начинается с них; - относительно родной реализации FreeRTOS под задачу и очередь у меня выделяется по одному блоку памяти TCB+Stack и QCB+Queue вместо отдельных. - в результате в реальности занимаются/освобождаются обычно 2-3-5-ну чуть больше блоков и найти подходящий по размеру проще и быстрее простым перебором из свободных. 6. Борьба с дефрагментацией: - склеивание соседних свободных блоков в один; - прежде всего поиск свободного блока равного размеру запрашиваемого - на самом деле достаточно не редкий вариант, особенно, если чуть приложить к этому усилия. Как строим: 1. Один общий связанный список, или отдельные для свободных и занятых. Использую один общий. Решающая причина - простой механизм склейки свободных блоков. При этом недостатки такого подхода нивелирутся тем, что ввиду (п.5) дефрагментация только в хвосте списка и длинна списка для поиска свободного эффективно сокращается использованием всего одного дополнительного указателя на первый свободный блок в общем списке. 2. На MCB выделено достаточно много памяти - 16 байт. Для максимально кастрированного варианта типа родных heap_*.с и с ограничением на размеры выделяемого блока можно было и в 4 байта уложиться, но см. "хотелки". Без особого напряга можно было в 12 байт уложиться, но тем неменее исходя из того, что например, для ARM стека выравнивание на 8 байт надо.... Пусть будет на данный момент 16 байт. Код typedef union type_size { unsigned long size; struct { unsigned long xlen:24; unsigned long type:8; }; }type_size;
// Memory Control Block (MCB) typedef struct heap_mcb { struct heap_mcb *next; // Указатель на следующий MCB // mcb.next последнего MCM всегда указывает на // первый MCB. struct heap_mcb *prev; // Указатель на предыдущий MCB. // Для первого MCB этот указатель указывает // сам на себя. union type_size ts; // Размер блока памяти и тип блока
void *ow; // ТСВ Владельца блока памяти // Собственно контролируемый блок памяти расположен сразу за MCB } heap_mcb;
// Структура-описатель HEAP (тип-структура t_heap) typedef struct heap_t { // Указатель на начало heap (первый MCB) struct heap_mcb *start; // Указатель на первый свободный MCB struct heap_mcb *freem; // RAW размер HEAP unsigned long hsize; } heap_t; Осталось откомментировать и выложить исходники. Завтра...
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Oct 18 2008, 19:47
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Оптимально-простой в соответствии с ранее изложенными принципами менеджер памяти. Подгибать, немного по месту, естественно, надо. Инициализация у меня, например, в одном из применений выглядит примерно так: Код #pragma segment="HEAP_RTOS" #pragma segment="XXX_STACK" void init_system_heap( int add_ram_id ) { system_heap.start = (heap_mcb *)(__segment_begin( "HEAP_RTOS")); system_heap.freem = (heap_mcb *)(__segment_begin( "HEAP_RTOS")); system_heap.hsize = (ulong)(__segment_begin( "XXX_STACK")) - (ulong)(__segment_begin( "HEAP_RTOS")) + 1;
heapinit( &system_heap ); if( add_ram_id == 2148 ) // LPC2148 USB Memory as General prupose RAM heapadd( &system_heap, (void *)0x7FD00000, 0x2000 );
} Для стандартной FreeRTOS можно для начала обертки сделать Код #define pvPortMalloc( size ) malloc_z( &system_heap, (size), MARK_SYSTEM, NULL ) #define vPortFree( ptr ) free_z( &system_heap, (ptr) )
Прикрепленные файлы
MEM.rar ( 3.2 килобайт )
Кол-во скачиваний: 318
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Nov 12 2008, 04:26
|

Местный
  
Группа: Участник
Сообщений: 209
Регистрация: 7-12-04
Из: Томск
Пользователь №: 1 382

|
Прикрутил к FreeRTOS TLSF~3kB RAM уходит на таблицу. Не нашёл описания на кучу дефайнов в tlsf.c, походу минимальный выделяемый блок 128 байт.
freertos_tlsf.zip ( 7.98 килобайт )
Кол-во скачиваний: 303
|
|
|
|
|
Apr 22 2010, 11:05
|

Знающий
   
Группа: Свой
Сообщений: 943
Регистрация: 6-07-04
Из: Санкт-Петербург
Пользователь №: 274

|
Первый выделенный блок не освобождается. Наверное перекрестную проверку нужно изменить с Код xptr = tptr->prev; if( ( xptr->next != tptr )||( mem_ptr < heap->start ) ) { xTaskResumeScheduler(); return; } на Код xptr = tptr->prev; if ( ((xptr != tptr) && ( xptr->next != tptr )) || ( mem_ptr < (void*)heap->start ) ) { xTaskResumeScheduler(); return; }
|
|
|
|
|
Jul 15 2013, 07:06
|
Участник

Группа: Участник
Сообщений: 64
Регистрация: 14-07-08
Пользователь №: 38 916

|
Исходники аллокатора от zltigo оказались очень полезными. Их, правда, пришлось почти полностью переписать, но идея, положенная в основу самая правильная. В результате получилась heap, которая при размере в 15 килобайт устойчиво держится в системе FreeRTOS, lwip (полный) и FatFS.
Heap_mang.rar ( 3.98 килобайт )
Кол-во скачиваний: 285
|
|
|
|
|
Jul 17 2013, 06:29
|
Участник

Группа: Участник
Сообщений: 64
Регистрация: 14-07-08
Пользователь №: 38 916

|
Вот это и было одной из причин использовать собственный аллокатор. На моей плате хеапы из дистрибутива FReeRTOS увеличивали размер кучи после просмотра двух-трех страниц lwipa и чтения пары килобайт из конфигурационных файлов. Оказалось что они почти не следят за освободившимися блоками, не умеют их объединять. Системный malloc приводил к таким же результатам - ему требовался большой стек.
|
|
|
|
|
Dec 4 2014, 13:13
|
Участник

Группа: Участник
Сообщений: 20
Регистрация: 23-01-12
Пользователь №: 69 823

|
Добрый день, коллеги! Хочется более точно понять как и откуда выделяется память во FreeRTOS и особенности функционирования отдельных выделяльщиков. Проект в IARe, в конфигурации линковщика есть параметр "heap". Так ли я понимаю, что при использовании heap_1.c, heap_2.c, heap_4.c для оси выделяется динамическая память размером "configTOTAL_HEAP_SIZE".
Вопрос 1. Откуда она выделяется? Т.е. "configTOTAL_HEAP_SIZE" это часть "heap" или "configTOTAL_HEAP_SIZE" - это память, забираемая плюсом к "heap"? Т.е. сколько мне остается на переменные проекта :-)
Вопрос 2. Для heap_3.c размер кучи - это "heap" линковщика?
Вопрос 3. В последних версиях FreeRTOS heap_4.c (heap_5.c) имеет все равно проблемы с фрагментацией?
Вопрос 4. Если память выделяется динамически на этапе старта - инита оси, стеков и пр., а в дальнейшем изменения задач, мутексов и динамически выделяемых данных не предвидится, то есть ли смысл париться альтернативным кодом аллокаторов?
|
|
|
|
|
Dec 8 2014, 13:11
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(MiG-3 @ Dec 4 2014, 17:13)  Так ли я понимаю, что при использовании heap_1.c, heap_2.c, heap_4.c для оси выделяется динамическая память размером "configTOTAL_HEAP_SIZE". Не понял что значит "для оси выделяется динамическая память"? configTOTAL_HEAP_SIZE задает объем памяти, доступный через pvPortMalloc. Память с его помощью выделяет сама ОС, и он же может использоваться в пользовательском коде... Цитата Вопрос 1. Откуда она выделяется? Т.е. "configTOTAL_HEAP_SIZE" это часть "heap" или "configTOTAL_HEAP_SIZE" - это память, забираемая плюсом к "heap"? Т.е. сколько мне остается на переменные проекта :-) Есть массив размера configTOTAL_HEAP_SIZE, из него память и выделяется. Цитата Вопрос 2. Для heap_3.c размер кучи - это "heap" линковщика? Код void *pvPortMalloc( size_t xWantedSize ) { void *pvReturn;
vTaskSuspendAll(); { pvReturn = malloc( xWantedSize ); } xTaskResumeAll(); return pvReturn; } КО подсказывает, что да  Цитата Вопрос 3. В последних версиях FreeRTOS heap_4.c (heap_5.c) имеет все равно проблемы с фрагментацией? Я сижу на 7.4.0, на моих применениях полет нормальный. heap_4 выполняет склейку соседних блоков памяти при освобождении. Цитата Вопрос 4. Если память выделяется динамически на этапе старта - инита оси, стеков и пр., а в дальнейшем изменения задач, мутексов и динамически выделяемых данных не предвидится, то есть ли смысл париться альтернативным кодом аллокаторов? Используй heap_1 да и все. Она не освобождает память, поэтому реализация простая и очень быстрая...
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|