Перейти к содержанию
    

FreeRTOS и свободная память в heap

Доброго дня всем!

Использую порт для PIC18, и все вроде бы хорошо, но подобрался уже к лимиту по ОЗУ.

И решил свободную heap часть уменьшить до 0. У меня простейшая модель памяти heap_1 и по ходу дела я не выделяю новые объемы, а только в самом начале приложения. И таким образом, я считал оставшийся свободные байты и вычел их из configTOTAL_HEAP_SIZE. Почему то при свободном нуле байт - он не заработал в принципе. Оставляю ему пару сотен свободных байт - работает. Отлаживаться крайне неудобно на PIC18, тыкаюсь-тыкаюсь и все равно не могу избавиться от свободной памяти.

Ведь прерывания использую стек задач?

И вообще это нормально дойти до 0 незанятой памяти?

Я уже крутил стеками задач, я переставлял местами задачи, чтобы в heap они выделали память в разной очередности, чтобы понять, что именно даёт сбой. Ни на что не влияет, только нужна свободная память ему...

Изменено пользователем kan35

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 минут назад, kan35 сказал:

У меня простейшая модель памяти heap_1 и по ходу дела я не выделяю новые объемы, а только в самом начале приложения.

Зачем тогда вообще куча нужна? "подобрался уже к лимиту по ОЗУ" и при этом впустую тратите память на ненужную кучу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

50 минут назад, kan35 сказал:

И таким образом, я считал оставшийся свободные байты и вычел их из configTOTAL_HEAP_SIZE

может посчитали неправильно? попробуйте вычитать меньше.

А вообще, да: куча здесь и не нужна. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 hours ago, jcxz said:

Зачем тогда вообще куча нужна? "подобрался уже к лимиту по ОЗУ" и при этом впустую тратите память на ненужную кучу.

Да, если честно, куча heap_1 это громко сказано, что это куча, с минимумом сервиса и перерасхода практически ноль. Для платформы PIC18 она удобна на самом деле. Я в ней аллоцирую массивы для работы, иначе в потоке я не могу сделать выделение переменных на более, чем около 100 байт... такая кривая архитектура, но пока приходится работать на нем.

Но похоже я понял в чем дело, программный таймер вроде портил мне жизнь... увеличил стек под него, хотя там вообще никаких вычислений, но видимо прерывания выделяли область в его стеке больше, чем я думал. Оставляю свободной памяти 1 байт теперь и все нормально.

Спасибо всем!

Изменено пользователем kan35

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я в последнее время перенастраиваю всё на статическую аллокацию и выключаю хип. Памяти экономится много, т.к. ее отжирает только стек который ты указываешь, а все хвостики на запас хипа твой бонус.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, seniorandre said:

Я в последнее время перенастраиваю всё на статическую аллокацию и выключаю хип. Памяти экономится много, т.к. ее отжирает только стек который ты указываешь, а все хвостики на запас хипа твой бонус.

heap_1 отжирает только 2 байта на свою работу:

static size_t xNextFreeByte = ( size_t ) 0;

И я готов потерять их 🙂

В моем случае контроллер с дурацким псевдо-постраничным доступом, который я, впрочем, победил, настроив оптимизацию, а именно отключив "banking optimizer". Но до этого я успел помучаться, так как линкер размещал переменные в алфавитном порядке и карту памяти было просто невозможно читать...  И тогда было удобно пользоваться аллокатором фриртоса тем самым можно было легче контроллировать положение каждого стека и каждого массива, так как все они лежали именно в хронометрическом порядке по мере создания.

К тому же как я написал выше, я не могу создать локальных переменных более, чем на ~100байт, это глупое ограничение архитектуры опять же.  И аллокация хотя бы массивов - вполне удобный инструмент для данного случая, иначе была бы куча ненужных глобальных переменных...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, kan35 сказал:

heap_1 отжирает только 2 байта на свою работу:

А как происходит выделение блока памяти? Имхо: должен создаваться заголовок блока (занимающий несколько байт), в котором указан его размер и ещё какая-то инфа. Нужный для последующего освобождения блока (ведь куча не знает, что вы не собираетесь его освобождать).

1. Т.е. - на каждый выделенный блок тратится ещё место для заголовка. Чего нет при статическом распределении.

2. Плюс ещё расходы ОЗУ - на хранение указателя для каждого выделенного блока. Что также не нужно при статическом распределении.

3. Кроме того: Использование динамически выделенных блоков памяти должно увеличивать расход регистров, стека в целом по всему коду. И должно в замедлять работу программы в целом, делать программу более громоздкой.

 

PS: Так что - лукавите. Общий проигрыш от использования дин.памяти вместо статической, должен быть существенным.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

57 minutes ago, jcxz said:

Имхо: должен создаваться заголовок блока (занимающий несколько байт), в котором указан его размер и ещё какая-то инфа. Нужный для последующего освобождения блока (ведь куча не знает, что вы не собираетесь его освобождать).

Во FreeRTOS несколько реализаций heap, разной степени примитивности. В этой освобождение блоков не предусмотрено.

https://www.freertos.org/a00111.html

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На PIC18, да RTOS? Смело 🙂

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

В целом, раз вы не создаете/удаляете динамически объекты, то целесообразно перейти в статический режим распределения. Подробности - в мануале FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensions

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, EdgeAligned сказал:

Так же, каждая задача, очередь и тп имеет свой заголовок

А это-то здесь причем? При статическом выделении они никуда не денутся.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Заголовки задач никуда не денутся, зато заголовки блоков выделенной памяти уберутся. Ну и сейчас на память боюсь ошибиться, но по-моему, при статическом создании задачи у нее заголовок занимает меньше места. Но это надо проверить, на память не помню.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 часов назад, EdgeAligned сказал:

Но это надо проверить, на память не помню.

проверил) в типе tskTCB есть такое:

	
    tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
	#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
		uint8_t	ucStaticallyAllocated; 		/*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
	#endif

но только когда используется и статическое и динамическое выделение совместно. Собственно, это поле для того и служит чтобы определить, каким образом был выделен контрол блок (заголовок, если правильно вас понял).

В конрол-блоках очередей (семафоры, мьютексы) - такая же история

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 11/25/2023 at 10:59 PM, EdgeAligned said:

Заголовки задач никуда не денутся, зато заголовки блоков выделенной памяти уберутся. Ну и сейчас на память боюсь ошибиться, но по-моему, при статическом создании задачи у нее заголовок занимает меньше места. Но это надо проверить, на память не помню.

Как уже обсуждали, это heap_1 , который не имеет такой функции и потому не может высвобождать память, так что все нормально, потерь тут нет.

 

On 11/25/2023 at 7:31 PM, EdgeAligned said:

На PIC18, да RTOS? Смело 🙂

Глаза боятся))) Сначала ожидал, что контроллер будет ср..ть кирпичами и это будет ощущаться, но оказалось, что при 1мс такте у нас имеется 12000 операций на каждый тик времени, и этого оказалось достаточно, чтобы ОС не перегрузила проц собой. При желании время можно и загрубить. 

Если хотите отзыв про PIC18+FreeRTOS, сообщаю -  работает отлично, я крайне удовлетворен))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 14.12.2023 в 14:35, kan35 сказал:

Глаза боятся))) Сначала ожидал, что контроллер будет ср..ть кирпичами и это будет ощущаться, но оказалось, что при 1мс такте у нас имеется 12000 операций на каждый тик времени, и этого оказалось достаточно, чтобы ОС не перегрузила проц собой. При желании время можно и загрубить.

Кстати, про системный тик: 

Практически все пользователи (и я тоже) оставляют этот параметр по умолчанию. Но мало кому дествительно нужно каждую миллисекунду запускать планировщик, это чисто психологический параметр (О! одна миллисекунда! круто!). В реальности эту величину можно и поменять, например увеличить, чтобы меньше ресурсов жралось на пустое переключение задач.

Например, в очень шустром ESP32 (тактовая 240 МГц) по умолчанию тик выбран 10 миллисекунд, и это не мешает его езернетам и вайфаям- все делается через прерывания.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 hours ago, Ruslan1 said:

и это не мешает его езернетам и вайфаям- все делается через прерывания

Или через yeild(). В таком случае размер тика становится не принципиальным.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...