SashaBe 0 13 июня, 2011 Опубликовано 13 июня, 2011 · Жалоба Здравствуйте. Использую в своём проекте порт FreeRTOS для LPC1343. Заявленные в топике дефайны configMINIMAL_STACK_SIZE configTOTAL_HEAP_SIZE 1. Не понятны с точки зрения физики: как выделяется память для каждой задачи, куда деваются после этого остатки? 2. Что будет, если общий объем стеков задач в сумме с configTOTAL_HEAP_SIZE превысит объем памяти? 3. Что происходит, когда размеры локальных переменных в таске превышают объём configMINIMAL_STACK_SIZE. 4. Как можно объяснить такое наблюдение: configMININAL_STACK_SIZE 300 configTOTAL_HEAP_SIZE 6*1024 В одной из 3х созданных задач есть структура объемом 216 байт и ещё кое-что по-мелочи. Но самое главное, код работает. Меняем просто configTOTAL_HEAP_SIZE 5*1024 - и всё умирает. Впрочем, программа умирает также, когда из трех тасков в двух размер стека задается configMININAL_STACK_SIZE. а в третьей - самой прожорливой configMININAL_STACK_SIZE*2. Верно ли использование этого дефайна в качестве задаваемого размера стека при создании таска или он может быть и поменьше, а для каждой задачи происходит какая-то проверка, не пытаешься ли ты создать задачу со стеком меньше минимального? 5. Наверное уже набившая оскомину тема с выделением и освобождением памяти внутри тасков: чем отличается использование malloc() и free() от специальных функций pvPortMalloc() и vPortFree(). Буду благодарен за ответы по существу и за ссылки на подробные объяснения в других местах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LightElf 0 14 июня, 2011 Опубликовано 14 июня, 2011 (изменено) · Жалоба Складывается ощущение, что вы не совсем понимаете как оно крутится. FreeRTOS использует кучу для создания своих структур (задач, списков, очередей, семафоров) и стеков задач. В составе FreeRTOS есть три варианта кучи: heap_1.c, heap_2.c и heap_3.c heap_1.c - простейший вариант. По сути - эмулятор динамического распределения без освобождения. Пригоден для случаев, когда объекты RTOS (задачи, очереди, семафоры и т.д.) создаются один раз и никогда не уничтожаются. Ситуация, как ни странно, довольно распространенная. heap_2.c - чуть сложнее. Есть возможность освобождать память, но нет дефрагментации свободных блоков. Пригоден в некоторых редких случаях. heap_3.c - обертка над стандартными malloc/free. Функциональность зависит от стандартной библиотеки используемого компилятора. Какой вариант кучи выбрать (или свой написать) - решает программист. Для первых двух вариантов configTOTAL_HEAP_SIZE задает размер кучи. Для третьего - размер кучи задается средствами линкера/компилятора/библиотеки. configMINIMAL_STACK_SIZE задает размер стека для IDLE TASK. Более самой FreeRTOS нигде не используется. 1. Не понятны с точки зрения физики: как выделяется память для каждой задачи, куда деваются после этого остатки? Каждой задаче выделяется только свой стек. Выделяется он из кучи FreeRTOS (то есть из configTOTAL_HEAP_SIZE). Глобальные и статические переменные выделяются линкером и FreeRTOS к ним сугубо перпендикулярна. Остатки что физической памяти, что кучи FreeRTOS - никуда не деваются и просто не используются. 2. Что будет, если общий объем стеков задач в сумме с configTOTAL_HEAP_SIZE превысит объем памяти? объем стеков с configTOTAL_HEAP_SIZE не суммируется, а наоборот из него вычитается. Если при создании задачи в куче не хватает памяти для стека - то задача не будет создана. 3. Что происходит, когда размеры локальных переменных в таске превышают объём configMINIMAL_STACK_SIZE. Если объем локальных переменных превысит размер стека (который задается при создании задачи), то скорее всего система сдохнет. Есть примитивная система диагностики, которая иногда может отследить нарушение границы стека и тогда будет вызван соответствующий хук (StackOverflowHook если не склероз). 4. Как можно объяснить такое наблюдение: configMININAL_STACK_SIZE 300 configTOTAL_HEAP_SIZE 6*1024 В одной из 3х созданных задач есть структура объемом 216 байт и ещё кое-что по-мелочи. Но самое главное, код работает. Меняем просто configTOTAL_HEAP_SIZE 5*1024 - и всё умирает. "Имя сестра, имя!". Процессор какой? configTOTAL_HEAP_SIZE задается в байтах, а configMINIMAL_STACK_SIZE - в portBASE_TYPE, который на армах имеет тип int. Для случая арма ваши три задачи займут 3*300*4 = 3.6 кБ. Плюс Idle Task еще 1.2 кБ. Вот уже почти ваши 5*1024, а ведь еще есть Task Control Block, очереди-семафоры и т.д. Впрочем, программа умирает также, когда из трех тасков в двух размер стека задается configMININAL_STACK_SIZE. а в третьей - самой прожорливой configMININAL_STACK_SIZE*2. Верно ли использование этого дефайна в качестве задаваемого размера стека при создании таска или он может быть и поменьше, а для каждой задачи происходит какая-то проверка, не пытаешься ли ты создать задачу со стеком меньше минимального? Ничего не проверяется. Скорее всего памяти в куче у вас не хватает. 5. Наверное уже набившая оскомину тема с выделением и освобождением памяти внутри тасков: чем отличается использование malloc() и free() от специальных функций pvPortMalloc() и vPortFree(). malloc() обычно не многозадачен. Зачастую - избыточен по функционалу. И время выполнения непредсказуемо. Потому и не любят его в мелких системах. Изменено 14 июня, 2011 пользователем LightElf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться