Как вы организуете код во встроенных проектах?

Проекты с высокой степенью встраивания (ограниченный код и размер оперативной памяти) создают уникальные проблемы для организации кода.

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

Тем не менее, я пытался организовать свой код соответствующим образом:

  1. зависит от оборудования (драйверы, инициализация)
  2. конкретное приложение (вряд ли будет использоваться повторно)
  3. многоразовый, аппаратно-независимый

Для каждого модуля я стараюсь придерживаться одного из этих трех типов.

Из-за ограниченного размера встроенных проектов и упора на производительность часто сохраняется такая организация.

Для некоторого контекста мой текущий проект представляет собой ограниченное приложение DSP на MSP430 с флэш-памятью 8 КБ и оперативной памятью 256 байт.


person JeffV    schedule 19.10.2008    source источник


Ответы (6)


Я написал и поддерживал несколько встроенных продуктов (более 30) на различных целевых микропроцессорах, включая MSP430. «Правила большого пальца», с которыми я добился наибольшего успеха, таковы:

  • Постарайтесь максимально разделить общие концепции на модули (например, отделить код драйвера от кода приложения). -- Это облегчает обслуживание и повторное использование/перенос проекта на другой целевой микро в будущем.
  • НЕ НАЧИНАЙТЕ с самого начала беспокоиться об оптимизированном коде. Попробуйте сначала решить проблему с доменом, а уже потом оптимизировать. -- Ваш целевой микро может обрабатывать гораздо больше "вещей", чем вы могли бы ожидать.
  • Работайте над обеспечением удобочитаемости. Хотя кажется, что у большинства встроенных проектов короткие циклы разработки, проекты часто живут дольше, чем вы могли бы ожидать, и другому разработчику, несомненно, придется работать с вашим кодом.
person Nate    schedule 19.10.2008

Я работал над 8-битными процессорами PIC с аналогичными ограничениями.

Единственное ограничение, которого у вас нет, — это количество комментариев, которые вы делаете, или то, что вы выбираете для имен своих методов, переменных и т. д. Воспользуйтесь преимуществом. Ограничения по скорости и размеру иногда превосходят организацию, но вы всегда можете объяснить.

Еще один совет — разбить логический исходный файл на еще большее количество частей, чем вам нужно, а затем связать их, #include поместив в единицу компиляции. Это позволяет вам иметь много повторно используемого кода (даже одну процедуру на файл), но комбинировать в любом порядке, который вам нужен. Это полезно, например. когда вы пытаетесь соблюсти ограничения на размер единицы компиляции или выбираете, какие общие подпрограммы вам нужны в следующем проекте.

person Jason Cohen    schedule 19.10.2008
comment
Важно отметить, что с некоторыми встроенными микрокомпиляторами выгодно объединять несколько файлов в один большой #included беспорядок, в то время как с другими лучше разделить их на более мелкие части. Я бы хотел, чтобы компиляторы, которые я использовал, давали несколько лучший контроль над организацией памяти без необходимости искусственно перестраивать исходный код. - person supercat; 02.02.2011

Я пытаюсь организовать это так, как если бы у меня было неограниченное количество ОЗУ и ПЗУ, и обычно это работает нормально. Как упоминалось в другом месте, не пытайтесь оптимизировать его до тех пор, пока в этом нет крайней необходимости.

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

person Kyle Heironimus    schedule 22.10.2008

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

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

При этом довольно типичными являются следующие:

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

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

Исполнение/приложение, вероятно, поддерживается как отдельный модуль. Весь специфичный для оборудования код должен быть скрыт в hal (как упоминалось выше).

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


Исключительные обстоятельства, которые могут быть вызваны необычными ограничениями компилятора. например. Я сталкивался с некоторыми компиляторами, которые ожидают, что все подпрограммы обслуживания прерываний будут скомпилированы в одном объектном файле.

person Andrew Edgecombe    schedule 22.10.2008

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

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

person luiss    schedule 19.10.2008

Хотя это немного болезненно, один метод организации, который несколько распространен во встроенных библиотеках C, состоит в том, чтобы разделить каждую отдельную функцию и переменную в отдельный исходный файл C, а затем объединить полученный набор O-файлов в файл библиотеки.

Мотивация для этого заключается в том, что для большинства обычных компоновщиков единицей связывания является объект, для каждого объекта вы либо получаете весь объект, либо ничего из него. Поскольку существует отношение 1-1 между файлами C и объектными файлами, размещение каждого символа в собственном файле C дает каждому свой собственный объект. Это, в свою очередь, позволяет компоновщику извлекать только то подмножество функций и переменных, которые действительно используются.

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

person Gordon Wrigley    schedule 21.10.2008
comment
При написании универсальных/повторно используемых библиотек это определенно важно. - person Toybuilder; 22.10.2008
comment
Я не уверен насчет всех компиляторов, но компоновщик IAR включает только те функции, которые действительно вызываются, и пропускает не вызываемые. Нет необходимости разделывать ваши файлы C. - person Kyle Heironimus; 22.10.2008
comment
Вы также можете использовать более новые версии gcc, чтобы сделать это, но это требует изменения флагов как на компиляторе, так и на компоновщике, и если у вас есть скрипт ссылки, который также потребует изменений. - person Gordon Wrigley; 22.10.2008