реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> FreeRTOS Heap_x.c
FormatCft
сообщение Oct 17 2008, 19:14
Сообщение #16


Местный
***

Группа: Свой
Сообщений: 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.
Может уже разбирались с этой проблемой?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 17 2008, 21:29
Сообщение #17


Гуру
******

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



Цитата(sergeeff @ Oct 7 2008, 18:46) *
И излишества всякие, нехорошие ...

Думал просто oткомментировать немного и выложить heap manager для FreeRTOS, но получается, что сначала нужно описывать почему он сделан именно так sad.gif. Попробую:
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
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 18 2008, 19:47
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
FormatCft
сообщение Oct 18 2008, 20:04
Сообщение #19


Местный
***

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



Спасибо! ! ! Щас будем прикручивать smile.gif
Go to the top of the page
 
+Quote Post
Terminator
сообщение Nov 12 2008, 04:26
Сообщение #20


Местный
***

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



Прикрутил к FreeRTOS TLSF
~3kB RAM уходит на таблицу.
Не нашёл описания на кучу дефайнов в tlsf.c, походу минимальный выделяемый блок 128 байт.

Прикрепленный файл  freertos_tlsf.zip ( 7.98 килобайт ) Кол-во скачиваний: 303
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 17 2010, 13:06
Сообщение #21


Гуру
******

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



Сергей Борщ нашел потенциально суровый баг при освобождении памяти, если используются несколько пулов памяти.
Архив с исправлениями в приложении.
Прикрепленные файлы
Прикрепленный файл  MEM2.rar ( 3.34 килобайт ) Кол-во скачиваний: 306
 


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Dron_Gus
сообщение Apr 21 2010, 07:41
Сообщение #22


Профессионал
*****

Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861



Спасибо за исходники. Пошел подтачивать под ansi.


--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
Go to the top of the page
 
+Quote Post
Alex B._
сообщение Apr 22 2010, 11:05
Сообщение #23


Знающий
****

Группа: Свой
Сообщений: 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;
    }
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 22 2010, 11:10
Сообщение #24


Гуру
******

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



Цитата(Alex B._ @ Apr 22 2010, 13:20) *
Первый выделенный блок не освобождается.

Типа да, это тоже были особенности использования в системе, которая имеет как минимум одну idle задачу, которая занимает минимум один блок.
Если это не так, то добавить этот код надо.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Alex B._
сообщение Apr 22 2010, 11:16
Сообщение #25


Знающий
****

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



Цитата(zltigo @ Apr 22 2010, 15:25) *
Типа да, это тоже были особенности использования в системе, которая имеет как минимум одну idle задачу, которая занимает минимум один блок.

Да это понятно. Спасибо за исходники.
Go to the top of the page
 
+Quote Post
wave48
сообщение Jul 15 2013, 07:06
Сообщение #26


Участник
*

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



Исходники аллокатора от zltigo оказались очень полезными. Их, правда, пришлось почти полностью переписать, но идея, положенная в основу самая правильная. В результате получилась heap, которая при размере в 15 килобайт устойчиво держится в системе FreeRTOS, lwip (полный) и FatFS.
Прикрепленный файл  Heap_mang.rar ( 3.98 килобайт ) Кол-во скачиваний: 285
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Jul 16 2013, 19:38
Сообщение #27


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Раз уж подняли тему.
Модулей диагностики (хотя б печать занятых/свободных блоков) для штатных heap2/heap4 никто не делал? Вроде б очень нужная вещь для отладки, но найти я не смог.

Или все внешние прикручивают? Странно это...


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
wave48
сообщение Jul 17 2013, 06:29
Сообщение #28


Участник
*

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



Вот это и было одной из причин использовать собственный аллокатор. На моей плате хеапы из дистрибутива FReeRTOS увеличивали размер кучи после просмотра двух-трех страниц lwipa и чтения пары килобайт из конфигурационных файлов. Оказалось что они почти не следят за освободившимися блоками, не умеют их объединять. Системный malloc приводил к таким же результатам - ему требовался большой стек.
Go to the top of the page
 
+Quote Post
MiG-3
сообщение Dec 4 2014, 13:13
Сообщение #29


Участник
*

Группа: Участник
Сообщений: 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. Если память выделяется динамически на этапе старта - инита оси, стеков и пр., а в дальнейшем изменения задач, мутексов и динамически выделяемых данных не предвидится, то есть ли смысл париться альтернативным кодом аллокаторов?


Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Dec 8 2014, 13:11
Сообщение #30


Знающий
****

Группа: Свой
Сообщений: 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;
}

КО подсказывает, что да sm.gif

Цитата
Вопрос 3. В последних версиях FreeRTOS heap_4.c (heap_5.c) имеет все равно проблемы с фрагментацией?

Я сижу на 7.4.0, на моих применениях полет нормальный. heap_4 выполняет склейку соседних блоков памяти при освобождении.

Цитата
Вопрос 4. Если память выделяется динамически на этапе старта - инита оси, стеков и пр., а в дальнейшем изменения задач, мутексов и динамически выделяемых данных не предвидится, то есть ли смысл париться альтернативным кодом аллокаторов?

Используй heap_1 да и все. Она не освобождает память, поэтому реализация простая и очень быстрая...
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 10th July 2025 - 07:46
Рейтинг@Mail.ru


Страница сгенерированна за 0.01504 секунд с 7
ELECTRONIX ©2004-2016