Я также могу порекомендовать книгу Embedded C Майкла Дж. Понта.и Программирование встроенных систем Майкла Барра.
За 14 лет работы разработчиком встроенных систем я узнал, что "практика" часто не работает во встроенных системах.Когда в книге говорится, используйте тот или иной шаблон, это верно, если у вас неограниченная память и мощность процессора.
Мне пришлось нарушить почти все правила дизайна, когда в прошлом году я разрабатывал новую платформу FW для крупной компании.,Вы должны спросить себя, является ли хорошо известное и принятое решение лучшим для вашего проекта за счет размера кода или скорости?Вещи, чтобы иметь в виду.
Локальный или глобальный?
Подумайте дважды, прежде чем объявлять переменную.Локальные переменные создаются в стеке во время выполнения, в то время как глобальные переменные создаются один раз при загрузке системы.
Const хранится во флэш-памяти, занимает место и имеет то же время доступа, что и индексированные массивы.Лучше использовать определение типа cast, если вам не нужно ссылаться на них с помощью указателей:
#define kState_Idle (unsigned char)4
Это скомпилирует 4 в коде сборки вместо того, чтобы извлекать его из flash как переменную только для чтения.
Не используйте double или float, они очень медленные.Вместо этого используйте целочисленную математику.Избегайте математической библиотеки любой ценой:)
Локальные переменные, к которым обращаются внутри циклов (например, for, while и т. д.), замедляют процесс, объявляют их как переменные-регистры для увеличения скорости.
Использование раздела для размещения кода
Каркас C / C ++ копирует все переменные (включая константы) в ОЗУ.Большая трата пространства, если оно доступно только для чтения переменных.Строки также попадают в эту категорию, например, «Hello world».
Когда речь идет о C ++, шаблоны не так уж и важны, так же как и RTTI и исключения.Избегайте этого !!
Перегрузка и морфинг действительно помогут вам с хорошим планированием, ваш код будет компактным и быстрым.
Библиотеки
В зависимости от размера микроконтроллеров, вы, вероятно, избегаете включать любые STL.Мы сделали свои собственные версии get (), put () printf () и т. Д., Чтобы уменьшить размер кода.
Использование аппаратного обеспечения
Не забудьте изучить ваш микроконтроллер / ЦП, чтобы использовать аппаратное обеспечение до 100%. Например, вместо заполнения памяти memset или memcpy, используйте DMA, если он у вас есть.
Также изучите сборку.Очень часто в контроллере есть специальные инструкции, для выполнения которых требуется несколько строк кода C / C ++.Вы можете написать свои собственные C-функции в ассемблере, чтобы соединить их с вашим C / C ++ кодом.Очень хорошими примерами являются инструкции по установке / очистке битов или инструкции по управлению блоками.
Проверьте, какой размер данных использует контроллер.Например, если это 16-битная система, она, вероятно, постоянно читает 16 бит, даже если вы объявили символ.В этом случае для чтения символа требуется больше времени, чем для короткого, поскольку для этого требуется дополнительная маскировка.
Память
Помните, что внутренняя RAM намного быстрее, чем внешняя RAM.Вы можете поместить переменные или даже код во внутреннюю память для ускорения.
Flash обычно медленнее, чем RAM, особенно для записи.Однако размещение переменных, доступных только для чтения, к которым часто обращаются, обычно не является ничьей.Компилятор обычно обнаруживает часто используемую переменную и назначает внутренний регистр.
тестирование
Часто невозможно отослать отладочную информацию в хост-систему достаточно быстро, не влияя на производительность.В этих случаях создайте внутренний буфер отладки для хранения вашей информации и последующего ее анализа.
Измерьте время выполнения, переключая аппаратный вывод, оно занимает одну инструкцию по сборке и фактически не влияет на скорость выполнения.Контролируйте контакт с помощью логического анализатора или осциллографа.Мы использовали ns в часто используемых функциях для повышения общей производительности.
Документация по автоматически сгенерированному коду также является хорошим способом найти «странный» дизайн или решения.Мы использовали Doxygen с Graphviz для генерации диаграмм классов и отношений.Здесь мы получили хороший обзор и могли заметить «устаревшие» классы или не обновленные подсистемы (мы использовали метод разработки Agile)Хм .. Я могу продолжать и писать целую книгу об этом:)
Мы сделали принтер, печатающий 150 мм / с на 20 КБ ОЗУ (RTOS, переменные, коммуникационные буферы и куча) и 64 КБ Flash (загрузочный блок, код приложения и 2 флеш-диска) все внутренние, используя приведенные выше рекомендации в C ++.
Удачи!