В настоящее время мы используем 32-разрядный микроконтроллер PIC32. Он отлично работает для наших нужд, но мы также изучаем другие микроконтроллеры, которые могут подойти нам лучше + у нас есть другие проекты, для которых мы выбираем MCU. Для этой цели мы выбрали микроконтроллер SAM DA на базе ARM, который является тем же 32-разрядным, но основан на ARM (более популярен, чем PIC32 - в отрасли).
Теперь для PIC32 мы используем MPLAB, но для ARM cortex-M0 мы будем использовать Atmel Studio. Мы будем использовать C-язык на обеих платформах. Меня беспокоит то, что мы будем использовать два 32-битных микроконтроллера (от одной компании), но с разными архитектурами. Это потребует от нас изучения двух разных устройств и увеличит нашу «кривую обучения» + время доставки. Но с другой стороны, я также думаю, что, поскольку в обоих случаях мы будем использовать язык C, кривая обучения для ARM не должна быть услышана, и стоит также изучить этот процессор.
Мой главный вопрос: насколько велика разница в архитектуре, когда мы программируем на C-Language, поскольку она обеспечивает абстракцию внутренних частей микроконтроллера. И каковы основные различия в MPLAP и Atmel Studio , если учесть программирование на C-языке.
Ответы:
Это довольно самоуверенная тема. Я могу говорить за себя (AVR, ARM, MSP430).
Разница 1 (самая значительная) заключается в периферии. Каждый из MCU имеет похожие UART, SPI, таймеры и т. Д. - просто имена регистров и биты различны. Большую часть времени это была основная проблема, с которой мне приходилось сталкиваться при перемещении кода между чипами. Решение: напишите свои драйверы с общим API, чтобы ваше приложение могло быть переносимым.
Разница 2 в архитектуре памяти. Если вы хотите поместить константы во флэш-память на AVR, вы должны использовать специальные атрибуты и специальные функции для их чтения. В мире ARM вы просто разыменовываете указатель, потому что существует единое адресное пространство (я не знаю, как его обрабатывают маленькие PIC, но предположил бы, что они ближе к AVR).
Разница 3 заключается в объявлении и обработке прерываний.
avr-gcc
естьISR()
макрос. ARM имеет только имя функции (например, someUART_Handler () - если вы используете заголовки CMSIS и код запуска). Векторы прерываний ARM можно размещать в любом месте (включая ОЗУ) и изменять во время выполнения (очень удобно, например, если у вас есть два разных протокола UART, которые можно переключать). AVR имеет только возможность использовать векторы либо в «основной флэш-памяти», либо в «разделе загрузчика» (поэтому, если вы хотите обрабатывать прерывания по-другому, вы должны использоватьif
оператор).Разница 4 - режимы сна и управления мощностью. Если вам требуется минимальное энергопотребление, вам необходимо использовать все функции MCU. Это может сильно отличаться между MCU - некоторые имеют более грубые режимы энергосбережения, некоторые могут включать / отключать отдельные периферийные устройства. Некоторые MCU имеют регулируемые регуляторы, так что вы можете использовать их с более низким напряжением на более медленной скорости и т. Д. Я не вижу простого способа добиться такой же эффективности на MCU (скажем) с 3 глобальными режимами питания, а другой с 7 режимами питания и индивидуальное периферийное управление часами.
Единственная самая важная вещь при заботе о переносимости - это четко разделить ваш код на аппаратно-зависимые (драйверы) и аппаратно-независимые (приложения) части. Вы можете разработать и протестировать последний на обычном ПК с имитирующим драйвером (например, консоль вместо UART). Это спасло меня много раз, так как 90% кода приложения было завершено до того, как прототипное оборудование вышло из печи оплавления :)
На мой взгляд, хорошая вещь в ARM - это «монокультура» - доступность многих компиляторов (gcc, Keil, IAR ... и многие другие), множество бесплатных и официально поддерживаемых IDE (по крайней мере, для NXP, STM32, Silicon Labs, Nordic), множество инструментов отладки (SEGGER - особенно Ozone, ULINK, OpenOCD ...) и многие производители чипов (я даже не буду их называть). PIC32 в основном ограничен микрочипами (но это имеет значение только если вам не нравятся их инструменты.
Когда дело доходит до кода Си. Это на 99% то же самое,
if
утверждение то же самое, цикл работает таким же образом. Однако вы должны заботиться о родном размере слова. Например,for
цикл на AVR самый быстрый, если вы используете егоuint8_t
для счетчика, а на ARMuint32_t
самый быстрый тип (илиint32_t
). ARM должен будет каждый раз проверять 8-битное переполнение, если вы используете меньший тип.Выбор MCU и / или поставщика в целом в основном зависит от политики и логистики (если у вас нет четких технических ограничений, например: высокая температура - используйте MSP430 или Vorago). Даже если приложение может работать на чем угодно, и только 5% кода (драйверов) должны разрабатываться и поддерживаться в течение всего срока службы продукта - это все еще дополнительные расходы для компании. Во всех местах, где я работал, был любимый продавец и линейка MCU (например, «выбирайте любой Kinetis, если хотите, если нет очень веской причины выбирать что-то другое»). Также полезно, если у вас есть другие люди, которые обращаются за помощью, поэтому в качестве менеджера я бы избегал иметь отдел разработки из 5 человек, где все использовали совершенно разные чипы.
источник
Я использовал несколько микроконтроллеров от четырех разных производителей. Основная работа каждый раз - знакомство с периферией.
Например, сам UART не слишком сложен, и я легко нахожу порт для своих драйверов. Но в прошлый раз у меня ушло почти сутки на то, чтобы разобраться с тактовой частотой, прерыванием ввода-вывода, включением и т. Д.
GPIO может быть очень сложным. Набор битов, сброс битов, переключение битов, специальные функции включения / выключения, три состояния. Затем вы получаете прерывания: любой край, рост, падение, низкий уровень, высокий уровень, самоочищение или нет.
Затем есть I2C, SPI, PWM, таймеры и еще два десятка типов периферийных устройств, каждый со своими собственными часами, и каждый раз регистры отличаются новыми битами. Для всех из них требуется много много часов, читая таблицу данных, как установить, какой бит при каких обстоятельствах.
У последнего производителя было много примеров кода, которые я нашел непригодными. Все было абстрактно. Но когда я нашел его, код прошел шесть! уровни вызовов функций для установки бита GPIO. Хорошо, если у вас процессор 3 ГГц, но не на MCU 48 МГц. Мой код в конце был одной строкой:
Я пытался использовать более общие драйверы, но я сдался. На MCU вы всегда боретесь с пространством и тактами. Я обнаружил, что уровень абстракции первым выходит из окна, если вы генерируете конкретную форму волны в подпрограмме прерывания, называемой с частотой 10 кГц.
Так что теперь у меня все работает, и я планирую НЕ переключаться снова, если только по очень-очень веской причине.
Все вышеперечисленное должно амортизироваться в зависимости от того, сколько продуктов вы продаете и что экономите. Продажа миллиона: экономия 0,10 для переключения на другой тип означает, что вы можете потратить 100 000 человеко-часов на программное обеспечение. Продажа 1000 у вас есть только 100 потратить.
источник
OUTPUT_HI(n)
которого будет уступать код , эквивалентный ,GPIOD->bssr |= 0x400;
еслиn
это константа , как 0x6A, но называть простую подпрограмму , еслиn
IS не постоянный Тем не менее, большинство API поставщиков, которые я видел, варьировались от посредственного до ужасного.Это больше мнение / комментарий, чем ответ.
Вы не хотите и не должны программировать на C. C ++, при правильном использовании , намного лучше. (Хорошо, я должен признать, что при неправильном использовании он намного хуже, чем C.) Это ограничивает вас чипами, которые имеют (современный) компилятор C ++, что примерно всегда поддерживается GCC, включая AVR (с В некоторых ограничениях Filo упоминает о проблемах неравномерного адресного пространства), но исключая почти все PIC (PIC32 может поддерживаться, но я еще не видел приличного порта).
Когда вы программируете алгоритмы на C / C ++, разница между упомянутыми вами вариантами невелика (за исключением того, что 8 или 16-битная микросхема будет иметь серьезный недостаток, если вы выполняете большую 16, 32-битную или более высокую арифметику). Когда вам нужна последняя унция производительности, вам, вероятно, потребуется использовать ассемблер (либо ваш собственный, либо код, предоставленный поставщиком или третьей стороной). В этом случае вы можете пересмотреть выбранный вами чип.
Когда вы кодируете аппаратное обеспечение, вы можете использовать какой-либо уровень абстракции (часто предоставляемый производителем) или написать собственный (на основе таблицы данных и / или примера кода). Существующие абстракции C в IME (mbed, cmsis, ...) часто функционально (почти) правильны, но ужасно терпят неудачу в производительности (проверьте oldfarts rant о 6 уровнях косвенности для операции набора выводов), удобстве использования и переносимости. Они хотят предоставить вам всю функциональность конкретного чипа, который почти во всех случаях вам не понадобится, и, скорее, вам это не нужно, и он блокирует ваш код для этого конкретного поставщика (и, вероятно, именно этого чипа).
Это то, где C ++ может работать намного лучше: при правильном выполнении набор выводов может проходить через 6 или более уровней абстракции (поскольку это делает возможным лучший (переносимый!) Интерфейс и более короткий код), но в то же время обеспечивает интерфейс, который не зависит от цели. для простых случаев , и все еще приводят к тому же машинному коду, который вы написали бы на ассемблере .
Фрагмент стиля кодирования, который я использую, который может вызвать у вас энтузиазм или отвратить в ужасе:
На самом деле есть еще несколько уровней абстракции. Тем не менее, окончательное использование светодиода, скажем, для его включения, не показывает сложности или деталей цели (для ардуина uno или синей таблетки ST32 код будет идентичен).
Компилятор не пугается всех этих уровней, и поскольку в нем нет виртуальных функций, оптимизатор просматривает все (некоторые детали опущены, например, включение периферийных часов):
Вот как бы я написал это на ассемблере - если бы я понял, что регистры PIO могут использоваться со смещениями из общей базы. В этом случае я бы, наверное, но компилятор гораздо лучше оптимизирует такие вещи, чем я.
Поэтому, насколько мне известно, это так: напишите уровень абстракции для своего оборудования, но делайте это на современном C ++ (концепции, шаблоны), чтобы он не повредил вашей производительности. С этим на месте, вы можете легко переключиться на другой чип. Вы даже можете начать разработку на каком-то случайном чипе, который у вас есть, с которым вы знакомы, у вас есть хорошие инструменты для отладки и т. Д., И отложить окончательный выбор до следующего (когда у вас будет больше информации о необходимой памяти, скорости процессора и т. Д.).
IMO - одна из ошибок встроенной разработки - сначала выбрать чип (на этом форуме часто задают вопрос: какой чип выбрать?). Лучший ответ, как правило, не имеет значения.)
(edit - ответ на вопрос «Значит, производительность будет выше, C или C ++ будут на одном уровне?»)
Для одинаковых конструкций C и C ++ одинаковы. C ++ имеет гораздо больше конструкций для абстракции (всего несколько: классы, шаблоны, constexpr), которые, как и любой инструмент, могут быть использованы как во благо, так и во вред. Чтобы сделать обсуждение более интересным: не все согласны с тем, что хорошо или что плохо ...
источник
Если я правильно понимаю, вы хотите знать, какие специфические особенности архитектуры платформы «всплывают» в вашей языковой среде C, что затрудняет написание поддерживаемого, переносимого кода на обеих платформах.
C уже достаточно гибок в том смысле, что это «переносной ассемблер». На всех выбранных вами платформах имеются коммерческие компиляторы GCC, поддерживающие языковые стандарты C89 и C99, что означает, что вы можете запускать одинаковый код на всех платформах.
Есть несколько соображений:
Некоторые платформы / компиляторы могут скрывать это «ограничение» лучше, чем другие. Например, на AVR вам нужно использовать определенные макросы для чтения данных ПЗУ. На PIC24 / dsPIC также доступны специальные инструкции tblrd. Однако, кроме того, некоторые части также имеют функцию «видимости программного пространства» (PSVPAG), которая позволяет отображать страницу FLASH в RAM, делая немедленную адресацию данных доступной без tblrd. Компилятор может сделать это довольно эффективно.
ARM и MIPS - это Von Neumann, поэтому области памяти для ROM, RAM и периферийных устройств упакованы на 1 шину. Вы не заметите никакой разницы между чтением данных из RAM или «ROM».
С другой стороны, PIC24 позволяет операциям ALU считывать и записывать данные напрямую через косвенную адресацию (даже с модификациями указателей ..). Это имеет некоторые характеристики от CISC-подобной архитектуры, поэтому 1 инструкция может выполнять больше работы. Такая конструкция может привести к более сложным ядрам процессора, снижению тактовой частоты, повышению энергопотребления и т. Д. К счастью для вас, эта часть уже разработана. ;-)
Эти различия могут означать, что PIC24 может быть «более мощным» по сравнению с операциями ввода / вывода, чем аналогично синхронизированный чип ARM или MIPS. Тем не менее, вы можете получить гораздо более высокую частоту ARM / MIPS для таймера при тех же ценовых / упаковочных / конструктивных ограничениях. Я полагаю, что для практических целей, я думаю, что много «изучения платформы» понимает, что архитектура может и не может делать, как быстро будет выполняться несколько операций и т. Д.
Эти различия могут быть в некоторой степени заложены в драйверах устройств, но, в конце концов, встроенная прошивка имеет высокий уровень связи с аппаратным обеспечением, поэтому иногда нельзя избежать нестандартной работы.
Кроме того, если вы покидаете экосистемы Microchip / бывшего Atmel, вы можете обнаружить, что для запуска деталей ARM требуется больше настроек. Я имею в виду с точки зрения; Включение часов для периферийных устройств, затем настройка периферийных устройств и их «включение», настройка NVIC отдельно и т. д. Это только часть кривой обучения. Если вы не забудете сделать все эти вещи в правильном порядке, то в какой-то момент написание драйверов устройств для всех этих микроконтроллеров будет довольно схожим.
источник
Да и нет. С точки зрения программиста, вы идеально скрываете детали набора команд. Но это в некоторой степени уже не имеет отношения к периферийным устройствам, которые составляют весь смысл написания программы, не являются частью набора команд. Теперь в то же время вы не можете просто сравнить 4096-битные части флэш-памяти между этими наборами команд, особенно если при использовании C объем потребления флэш-памяти в значительной степени определяется набором команд и компилятором, некоторые никогда не должны видеть компилятор (кашель PIC кашель) из-за того, сколько отходов этих ресурсов потребляется при компиляции. Другие флэш-потребление меньше накладных расходов. Производительность также является проблемой при использовании языка высокого уровня и вопросов производительности в приложениях MCU, поэтому она может иметь значение между затратами 3 доллара на плату для mcu или 1 доллара.
Если речь идет об упрощении программирования (за счет общей стоимости продукта), вы должны иметь возможность загрузить пакет разработчика для mcu таким образом, чтобы архитектура набора команд была чем-то, чего вы никогда не увидите, поэтому если это ваша основная задача, то это это не проблема. Это по-прежнему стоит вам денег, насколько стоимость продукта для использования этих библиотек, но, время выхода на рынок может быть короче, я считаю, что библиотекам требуется больше времени / работы, чтобы использовать по сравнению с непосредственным общением с периферийными устройствами.
В итоге, наборы инструкций - это наименьшее из ваших беспокойств, переходите к реальным проблемам.
источник