Comrade Bulkin Memory Blog

Мои заметки и статьи по тематике программирования МК, а также системного администрирования


Project maintained by firebull Hosted on GitHub Pages — Theme by mattgraham

Долго думал над содержанием, но всё-таки решил написать статью-сравнение Atmega vs STM32 и, так сказать, “экосистем” Arduino vs HAL. Попытаюсь немного зацепить и Mbed для ARM. Предыдущие статьи:

Вступление

Давайте немного определимся с понятиями и что же мы будем сравнивать.

Для начала зададимся вопросом, а корректно ли сравнивать 8-битную архитектуру МК Atmega/ATtiny и 32-битную ARM STM32?

Собственно, в этой статье я обсуждаю преимущества, которая даёт 32-битная архитектура в целом, а также преимущества МК STM32 относительно МК Atmega/ATtiny в частности. Вопрос из той же оперы, как стоит ли переходить с процессоров i486 на i7.

Я сам занимаюсь автоматикой. Так что и вижу я картину с точки зрения автоматики, в основном промышленной автоматики.

Немного теории о 8 битах

Часто сталкивался с заблуждением, что программа на 8-ми битных МК оперирует только 8-ми битными данными, потому смысла в переходе на 32-битные МК нет. На самом деле, например, простые целочисленные данные и указатели в 8-ми битных МК являются 16-ти битными. Поэтому, утрируя, при работе с такими данными, МК тратит дополнительные такты там, где 32-битное ядро тратит всего один. Плюс для доступа к таким данным 8-ми битный МК производит дополнительные операции чтения/записи и операции со стеком. На деле это приводит и к увеличению кода прошивки, и к увеличению потребления памяти.

32-битные же МК могут легко оперировать 8-, 16- и 32-битными данными за такт. Плюс наличие готовых команд для доступа к ним и преобразования.

А что с производительностью?

Тут можно обратиться к сухим синтетическим тестам, например CoreMark. Он хорош ещё и тем, что даёт показатель CoreMark/MHz. Просто навскидку из таблицы:

  • ATmega2560 (на частоте 8МГц): 0.53 CoreMark/MHz
  • ATmega644 (на частоте 20МГц): 0.54 CoreMark/MHz
  • STM32F103RB (на частоте 72МГц): 1.50 CoreMark/MHz
  • STM32F051C8 (на частоте 48МГц): 2.20 CoreMark/MHz

Ещё раз подчеркиваю, это показатель производительности на МГц частоты. Общая производительность вообще разгромная:

  • ATmega2560 (на частоте 8МГц): 4.25 CoreMark
  • ATmega644 (на частоте 20МГц): 10.21 CoreMark
  • STM32F103RB (на частоте 72МГц): 108.26 CoreMark
  • STM32F051C8 (на частоте 48МГц): 105.61 CoreMark

Я привёл примеры наиболее используемых МК из готовой таблицы.

Если ещё коснуться ARM, то они имеют набор команд Thumb, которые позволяют делать, например, множественные пересылки данных одной командой.

Давайте сюда ещё прибавим модуль FPU, который есть на всех STM32 начиная с серий F3xx. Значительно ускоряет вычисления с плавающей точкой. Конечно, можно изгаляться с псевдо-плавающей точкой, типа умножать такие числа на 1000 и считать их целыми. Но на деле это далеко не всегда возможно и удобно.

И ещё потом добавим DMA, который на порядок ускоряет работу с периферией и не только.

Выходит очень вкусно, я считаю.

А что с потреблением?

Тут всё по канонам. В сравнении с 32-бит, 8-битные МК производят в 4 раза больше циклов обращения к памяти и большее количество команд для копирования того же объема данных. Также, например, ARM позволяют выполнять по 2 команды Thumb за такт. У 32-бит меньше работы, меньше потребление.

Если говорить про переход в спящий режим, то у ARM есть фишка - проснулись по прерыванию, отработали его и сразу заснули. С учётом того, что отработает он быстрее, чем AVR 8-бит, потребление будет значительно меньше.

Также это всё значит, что и работаем на пониженном напряжении. Это 3.3В у STM32 против 5В у Atmega. Конечно, у Atmega можно снизить напряжение, но придётся снижать и частоту в разы. Если брать те же 3.3В, то придётся снизить частоту до 10МГц.

Это кстати, ещё преимущество для STM32. Далеко не вся периферия работает на 5В, поэтому приходится ставить дополнительный регулятор напряжения для неё при использовании ATmega/ATtiny.

Хотя, чего греха таить, я сам предпочитаю использовать импульсный регулятор на входе на 4.5-5В и потом опускаю линейником до 3.3В. Это особенно важно там, где используются ADC/DAC.

Ну и не забудем про такую серию у STM32, как Lxxx. Это МК с ультра-низким потреблением. Хотя они дороговаты. Но у них, зато, есть ещё и EEPROM на борту, как у Atmega/ATtiny.

А что с ценой?

Тут вообще момент прекрасный. Если брать прям вот аналогичный в плане ног и периферии STM32, выигрыш значительный. Плюс можно сэкономить на RTC и USB.

Если брать современную серию STM32 на Cortex M4 и Cortex M7, это F3xx и выше, там цена выше, конечно, но и плюшек море.

Замучил уже, сравнивай в таблице!

Я решил разбить сравнение на 4 части:

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

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

Я не буду брать цены с Ali, только Российские поставщики. Я не буду давать тут рекламу, могу в комментах ответить, где я покупаю. Всегда есть, где подороже, а где подешевле. Нам важны относительные цены. К тому же, через неделю они могут поменяться, все зависит от курса $.

И ещё. Дать корректное количество каналов PWM может быть не везде просто. Поэтому пишу везде приставку “до”. Я считаю те, которые всей кучей можно вывести на разные ноги.

Я везде в STM32 отмечаю наличие CRC32. Это очень важная и нужная фишка. Позволяет считать контрольные суммы налету. Очень нужно, если пишете свой протокол обмена данными, например. Для того же Modbus можно приспособить.

Все фотки самих чипов я делал на планшет, цифры сейчас нет под рукой. Все фото мои личные, фотал чипы из своих запасов.

Микро: ATtiny861A-SU vs STM32F030F4P6

Собственно решение для минимальных задач. Выбирал МК по доступности, количеству ног ну и более-менее нормальной периферии.

МК ATtiny861A-SU STM32F030F4P6
Корпус SOIC-20 TSSOP-20
Память 8kB Flash/512B SRAM 16kB Flash/4kB SRAM
Макс. частота 20MHz (16MHz Arduino) 48MHz
Основная периферия 1xSPI, 1xI2C 1xSPI, 1xI2C, 1xUSART
Таймеры 1x16-bit, 1x8-bit 5x16-bit
PWM до 3 каналов до 6 каналов
ADC/DAC 1x10-bit, 11 каналов 1x12bit, 9 каналов. Плюс два канала Vref и Temp
Доп. периферия - Модуль CRC 32-bit
Доп. информация EEPROM 512B DMA 5 каналов
Цена в партии от 5 шт. 85 руб. 40 руб.

Слева ATtiny, справа STM32. Разница в размерах впечатляет, особенно как узнаешь возможности этой финтифлюшки. chips

Мини: ATmega328P-AU vs STM32F103C8T6

Ну тут я не сильно мучился с выбором и взял два самых попсовых МК из обоих миров. На них куча разработок во всех областях, купить можно в чуть ли не в любом сельпо. Хоть они и не совпадают по ногам, но близки в сферах применения.

МК ATmega328P-AU STM32F103C8T6
Корпус TQFP-32 LQFP-48
Память 32kB Flash/2kB SRAM 64kB Flash/20kB SRAM
Макс. частота 20MHz (16MHz Arduino) 72MHz
Основная периферия 1xSPI, 1xI2C, 1xUSART 2xSPI, 2xI2C, 3xUSART
Таймеры 1x16-bit, 2x8-bit 4x16-bit
PWM до 6 каналов до 16 каналов
ADC/DAC 1x10-bit, 8 каналов. Плюс 1 канал Temp 2x12bit по 10 каналов. Плюс два канала Vref и Temp
Доп. периферия QTouch RTC, USB, CAN, Модуль CRC 32-bit
Доп. информация EEPROM 1kB DMA 7 каналов
Цена в партии от 5 шт. 110 руб. 120 руб.

Слева ATmega, справа STM32. При схожих размерах, ног у STM32 больше. chips

Средне: ATmega644PA-AU vs STM32F303CBT6

По опыту прошлой разработки знаю, что первым делом, когда 328-й уже не хватает, но 2560 ещё как-то слишком, ATmega644 лучший вариант. 44 ноги, периферия побогаче, памяти побольше и стоит по-божески. Думал включить сюда ATmega1284, но стоит у нас непотребных денег, решил всё-таки учесть цену.

Относительно STM32F303CB стоит заметить, что это очень сбалансированный чип по всем параметрам. Богатая периферия, много памяти, нормальная цена. Есть FPU, аппаратная поддержка RS485 (умеет аппаратно дёргать ногой направления передачи данных) и куча других плюшек.

МК ATmega644PA-AU STM32F303CBT6
Корпус TQFP-44 LQFP-48
Память 64kB Flash/4kB SRAM 128kB Flash/32kB SRAM
Макс. частота 20MHz (16MHz Arduino) 72MHz
Основная периферия 3xSPI, 1xI2C, 1xUSART 3xSPI, 2xI2C, 3xUSART
Таймеры 1x16-bit, 2x8-bit 1x32-bit, 9x16-bit
PWM до 6 каналов до 22 каналов
ADC/DAC 1x10-bit, 8 каналов DAC 12-bit на 2 канала. ADC 4x12-bit, всего 15 каналов. Плюс 3 канала Vref, Vbat и Temp. Плюс 4 канала со встроенных OPAMP.
Доп. периферия QTouch RTC, USB, 4xOPAMP Rail-to-Rail, CAN, Модуль CRC 32-bit, TouchSensing
Доп. информация EEPROM 2kB DMA 12 каналов, FPU
Цена в партии от 5 шт. 200 руб. 145 руб.

Слева ATmega, справа STM32. При сравнимом количестве ног, размер у STM32 меньше. chips

Макси: ATmega2560-16AU vs STM32F405VGT6

Ну выбор МК от AVR в этой категории очевиден. STM32F405 выбрал также из-за его сбалансированности. А ещё вкусной цене при таких-то характеристиках.

МК ATmega2560-16AU STM32F405VGT6
Корпус TQFP-100 LQFP-100
Память 256kB Flash/8kB SRAM 1MB Flash/192kB SRAM
Макс. частота 20MHz (16MHz Arduino) 168MHz
Основная периферия 1xSPI, 1xI2C, 4xUSART 3xSPI, 3xI2C, 4xUSART, 2xUART
Таймеры 4x16-bit, 2x8-bit 2x32-bit, 12x16-bit
PWM до 16 каналов до 32 каналов
ADC/DAC 1x10-bit, 16 каналов DAC 12-bit на 2 канала. ADC 3x12-bit, всего 16 каналов. Плюс 3 канала Vref, Vbat и Temp.
Доп. периферия QTouch RTC, USB, 2xCAN, SDIO, Модуль CRC 32-bit, TouchSensing
Доп. информация EEPROM 4kB DMA 16 каналов, FPU, Random number generator, FSMC memory controller
Цена в партии от 5 шт. 550 руб. 380 руб.

Выводы

Конечно, сложно сравнивать такие вещи. Если делать подробный анализ, утонешь в тоннах текста. Если чего-то не обсудить, куча людей будет возмущаться, а почему про это не сказал, а почему это не отметил. Всё куплено!

Где-то года полтора назад я сам наткнулся на подобное сравнение и был ошарашен. К тому моменту уже больше года у меня было несколько отладочных плат на STM32 и я всё никак не мог к ним подступиться. Но тогда твёрдо решил добить. Отложил дела и потратил месяц на изучение. Через вопли, бури возмущения, сопли и ярость. А теперь не понимаю, как я раньше жил на Atmega’х и Arduino.

Ладно. Хочу отметить некоторые вещи, которые здорово влияют на выбор с обеих сторон.

Плюсы Arduino и вообще.

  • Конечно же сама экосистема. Огромная база знаний, огромное коммьюнити
  • Библиотеки есть подо всё, прям вообще
  • Доступность шилдов подо всё и вся
  • Чрезвычайно низкий порог вхождения, вот для любого
  • На борту есть EEPROM, это очень удобно и круто.

Отдельно стоит отметить, что даже без Arduino программировать под Atmel довольно легко. Библиотеки, Atmel Studio и прочее.

Но есть и глобальные недостатки.

  • Из-за того же простого порога вхождения, качество библиотек в подавляющей своей массе просто ужасное. Я б даже сказал, отвратительное.
  • На Arduino нет нормальной отладки. Serial.print() - это нефига не отладка.
  • С Atmega никогда не получишь нормальной производительности. Нормального планировщика не воткнёшь. Они есть, конечно, даже FreeRTOS можно воткнуть, но памяти и так мало, а планировщики очень голодные. Потому не сделаешь нормальный интерфейс с хорошим откликом, не сделаешь контроллер с сотней прерываний и несколькими десятками устройств на периферии.
  • Куча народу возомнили себя крутыми спецами и штампуют дерьмо на отладочных платах и шилдах. Частенько промышленное дерьмо. Это, у меня лично, вызывает дикое негодование.
  • Сама по себе платформа, не смотря даже на то, что и STM32 тоже может работать с Arduino, подразумевает усреднение. Отсюда даже на нормальных чипах ты получаешь кастрата. И по-любому приходится лезть в дебри. Ну и в чём смысл тогда?
  • Если касаться Atmel Studio - это тяжелейший монстр, который даже на моем i5 с 24Gb и SSD тормозит так, как Quake на 486-м.

А что сказать хорошего про STM32?

  • Платформа изначально очень производительная. Как я писал выше, нет кучи недостатков 8-битных МК.
  • У тебя всегда изначально куча периферии. И ты выбираешь, на какие ноги её вешать и плату разводишь, как тебе удобно. А МК уже конфигурируешь исходя из этого.
  • Из неочевидного, например, на любую ногу можно сделать как PullUP, так и PullDown. А это очень облегчает проектировку плат, поверьте.
  • HAL, на самом деле, очень мощный инструмент. Хотя некоторые его хают за громоздкость, но на деле это в основном набор готовых #define, которые сильно облегчают написание и чтение кода. И переносимость!
  • Отладка практически на любом инструменте, почти в любой среде работает на ура из коробки. А это в любой момент все переменные, как на ладони. И точки, и даже графики. Я вообще не пользуюсь ничем, что выводило бы данные в консоль. Зачем? Тратить время на написание этих шаблонов, которые потом вычищать из продакшена?
  • STM32CubeMX вообще панацея. За пару минут переносится код на почти любой другой STM32. Что-то поменял? Нет проблем, галочки расставил, пересобрал проект и всё!
  • Тот же SPI на F405 можно запустить на 41Мбит! Я просто EEPROM на SPI пользую на 21Мбит. А ещё прибавьте к нему DMA и вообще красота! Летает!
  • А наличие USB и RTC почти во всех STM32?

Ладно, плюсами можно до бесконечности. Что из минусов есть:

  • Довольно трудный вход. Разобраться сходу не получится, нужно иметь базис.
  • Библиотек в свободном доступе не то чтобы нет. Есть и много. Но они либо под устаревший StdPerif, либо заточены под конкретного человека и его собственный набор библиотек. Либо и то, и другое сразу. Так, чтобы почти без доработки большая редкость. К сожалению, сложно абстрагировать библиотеку в STM32, они часто повязаны друг с другом и заточены подо что-то конкретное
  • Так что да, вам придётся писать свои библиотеки довольно часто. Даже под элементарные вещи вроде LCD1602
  • Вас будет бесить написание HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET) в сравнении с digitaWrite(LED1, HIGH). Вас будет бесить, что вы должны ВСЕГДА указывать размер буфера приёма. Ведь какая красота в Arduino Serial.available()! Нет, в STM32 мы тоже можете сделать подобное, но придётся взрыть тонны документации, чтоб понять некоторые неочевидные, но элементарные вещи.
  • Вас будет бесить переход к C99 после C++, но потом даже будете этому рады.
  • Вас будет бесить объем и количество документации по STM32. Но потом вы проникнетесь и увидите лаконичность и очень грамотную подачу относительно документации Atmel.
  • На борту нет EEPROM, кроме серии STM32Lxxxx, которая дорогая, как изумруд.

Стоит ещё отметить такую штуку, как Mbed. Довольно крутая вещь для IoT. Большое коммьюнити, мощная поддержка. Куча библиотек для всего. Хотя для моих задач не очень подходит. Посмотрите, если в чистом виде STM32 пугает. STM выпускает платы Nucleo под эту платформу. Так что есть готовые решения, есть =)

Ладно. Всего не отметишь. Обо всём не расскажешь. Каждый должен сам решить, стоит ли. Я вот прошел этот рубеж и безумно этому рад. Я не пошёл по простому пути Arduino -> RPi и в результате имею сейчас гораздо более мощные инструменты. Конечно, одноплатки нужны и они крутые. Туда и Linux можно накатить, и сервачок поднять с БД. Но это другая опера.

На сегодня всё, удачи!

Оригинал статьи опубликован на Pikabu