Как я могу использовать malloc()
и free()
функции в PIC? Я проверил stdlib.h
заголовок, и нет никаких упоминаний о них. Я использую MCC18.
Кто-нибудь должен был их использовать?
Они мне нужны, потому что я портирую библиотеку с Windows XP на PIC. Руководство по портированию говорит
адаптировать конкретные функции операционной системы к моим PIC
Но я не знаю, как "перевести" malloc()
и free()
функции.
Ответы:
Во многих приложениях нужно будет выделять память, но не нужно ничего освобождать, сохраняя то, что было выделено после нее. В такой системе все, что нужно сделать, это использовать компоновщик, чтобы определить массив, используя всю доступную оперативную память, установить указатель на начало этого массива, а затем использовать удобную простую функцию malloc:
Легко и просто, и всего два байта общих накладных расходов для любого количества распределений. Вызов free () для блока освободит этот блок и все после него.
Чуть более сложные шаблоны распределения могут быть обработаны с помощью двух указателей - один из которых распределяет содержимое из нижней части памяти, перемещаясь вверх, а другой - из верхней части памяти вниз. Также возможно использовать компактируемый сборщик мусора, если данные в куче однородны и известно, где находятся все внешние ссылки на них.
источник
malloc()
В микроконтроллерах это вообще считается «плохой вещью». Но, если вам это абсолютно необходимо, вы захотите найти стороннюю версию.Если вам повезет, код, который вы переносите, может не зависеть от повторного использования блоков памяти. Если это так, вы можете написать простой распределитель, который возвращает указатель в буфер ОЗУ, а затем увеличивает указатель на запрошенный размер блока.
Ранее я успешно использовал этот подход при переносе библиотек ПК на микроконтроллеры.
Ниже вы можете настроить распределитель с помощью
my_malloc_init()
и выделить память с помощьюmy_malloc()
.my_free()
есть, чтобы удовлетворить зависимость, но на самом деле не будет ничего делать. В конце концов, вам не хватит места, конечно.Чтобы это работало, вам нужно измерить наихудшую потребность в памяти для вашего кода (сделайте это на ПК, если это возможно), а затем настроить ее
HEAP_SIZE
соответствующим образом. Прежде чем войти в ту часть вашей библиотеки, которая требует динамической памяти, позвонитеmy_malloc_init()
. Перед повторным использованием убедитесь, что ничего не указывает наheap
.(примечание: в реальном мире может потребоваться выравнивание указателя, т. е. округление
heap_ptr
на 2 или 4 байта)Другой вариант - использовать более простую структуру размещения, чем
malloc()
обычно предоставляет, например FreeList , хотя это может не позволить вам выделять блоки переменного размера.источник
Это вряд ли является ответом на ваш вопрос, но динамическое распределение памяти обычно не одобряется в небольших средах оперативной памяти и в отсутствие операционной системы (например, в мире микроконтроллеров) ... пространство кучи, доступное во встроенной среде, обычно измеряется сотнями байтов ...
Реализация malloc и free - это, по сути, поддержка связанного списка структур «свободного сегмента», и, как вы можете себе представить, метаданные, связанные со свободными сегментами, не являются существенными по сравнению с объемом обычно доступной памяти, то есть «накладными расходами». «Управление динамическим пулом памяти потребляет значительное количество доступных ресурсов.
источник
Я не знаю, поддерживает ли стандартная библиотека C18
malloc
иfree
, но в Microchip App Note AN914 показано, как вы можете реализовать свою собственную.В любом случае, Томас и другие авторы предложили, что использование динамической памяти на PIC с очень малым объемом ОЗУ чревато опасностью. Вы можете быстро исчерпать непрерывное пространство из-за отсутствия более продвинутых менеджеров виртуальной памяти, которые дают вам полноценные ОС, что приводит к сбоям при выделении ресурсов и сбоям. Хуже того, он не может быть детерминированным и, скорее всего, будет затруднительным для отладки.
Если то, что вы делаете, действительно динамически определяется во время выполнения (редко для большинства встроенных вещей), и вам нужно только выделить место в паре очень особых случаев, я мог бы видеть это
malloc
иfree
быть приемлемым.источник
Ну, а насколько велик ваш PIC с точки зрения памяти?
malloc - очень неэффективный способ выделения памяти. Проблема заключается в том, что память может быть фрагментирована с частыми освобождениями и mallocs, и только с несколькими килобайтами памяти, ошибки выделения слишком распространены. Вполне вероятно, что если вы используете меньшую микросхему или более раннюю PIC18, то нет поддержки malloc, поскольку Microchip либо посчитал ее очень сложной для реализации (или, возможно, даже невозможной в некоторых случаях), либо недостаточно используемой для ее использования. стоило того. Не говоря уже об этом, но он также довольно медленный, вы смотрите на 1 цикл, чтобы использовать статический буфер, который уже доступен, и от 100 до 1000 циклов, чтобы сделать malloc.
Если вы хотите выделить статически, создайте такие вещи, как буфер для ваших функций sprintf (если есть, около 128 байт), буфер для вашей SD-карты (если есть) и так далее, до тех пор, пока вы не удалите необходимость в malloc. В идеале вы используете его только там, где это абсолютно необходимо, и не можете избежать статического распределения, но такие ситуации обычно редки и, возможно, являются признаком того, что вы должны смотреть на более крупные / более мощные микроконтроллеры.
И если вы разрабатываете / переносите «операционную систему» на PIC18 и если она поддерживает микроконтроллеры, она, вероятно, поддерживает статическое распределение. Например, SQLite3 поддерживает статическое распределение - вы выделяете ему большой буферный массив, и он использует его там, где это возможно, даже если это не для микроконтроллеров. Если это не так, то вы уверены, что он предназначен для небольшого PIC18?
источник
Если вы рассматриваете
malloc()
иfree()
для встроенного программного обеспечения , я предлагаю вам взглянуть на УНЦ / OS-II иOSMemGet()
иOSMemPut()
. Хотяmalloc()
позволяете выделить произвольный блок памяти,OSMem*()
дать вам фиксированный размер блок из предварительно выделенного бассейна. Я считаю этот подход хорошим балансом между гибкостьюmalloc()
и надежностью статического распределения.источник
AFAIK, чтобы сделать это правильно, вам действительно нужно смотреть на устройство с каким-то блоком управления памятью (MMU). Хотя механизмы динамического распределения для серии PIC18 существуют, на самом деле они не будут такими надежными - и, говоря о том, кто работает над прошивкой, которая раздвигает пределы серии PIC18, я могу сказать, что вы не получите большое приложение, если вы потратите все накладные расходы на менеджер памяти.
Лучшее решение: попытайтесь понять, что он делает и почему он требует динамического распределения. Посмотрите, не можете ли вы перефакторировать его для работы со статическим распределением. (Это может быть случай, когда это просто невозможно - если библиотека / приложение спроектировано так, чтобы делать что-то, что масштабируется свободно, или не имеет границ объема ввода, который может принять.) Но иногда, если вы действительно думаете, о том, что вы пытаетесь сделать, вы можете обнаружить, что возможно (и, возможно, даже довольно просто) использовать вместо этого статическое распределение.
источник