Assembler и C в рамках маломощных микроконтроллеров

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

И есть линейка своих собственных исполнительных устройств, модулей, датчиков и т.п. реализованных на AVR(в основном это ATmega168).

При этом данная линейка - это хобби, ее я реализую для себя и вкладываю туда функционал нужный мне, и пишу соответственно на том, что нравится мне. А не Вам, и не ради моды.

Меня часто спрашивают, почему я пишу прошивки для AVR микроконтроллеров на ассемблере.

Часто слышу стереотипы - ассемблер никому не нужен, очень сложный, нет переносимости, большие трудозатраты. И даже такие, как - на нем никто не пишет и Вы не должны, в общем я кому-то, получается, что-то должен.

Первое и пожалуй главное - ничто не научит работать с периферией лучше, чем кодинг на ассемблере.

Я применяю МК по прямому назначению - работа с периферией, если мне потребуется рисовать UI или считать математику я буду смотреть в сторону SoC или вообще в сторону микрокомпьютеров типа всяческих PI, где буду использовать более подходящий высокоуровневый язык чем Си.

Кстати по этой причине мне не особо интересны STM микроконтроллеры.

Второе - ассемблер не сложный, он имеет всего несколько десятков команд, это сложно запомнить? Главная сложность в том, что на ассемблере программист многие алгоритмы составляет сам, чем и добивается существенной оптимизации. Т.е нужно уметь думать головой. И дело не в том, что компилятор что-то может или не может, дело в принципе в подходе к самому программированию. В Си вы не задумываясь воспользуетесь тяжелой функцией, вместо пары тройки команд на ассемблере.

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

Третье, как вообще можно отлаживать даже программу на Си для МК, не зная ассемблера? Как можно написать оптимальный бутлоадер не зная ассемблера? Как посчитать такты в критических по времени местах? Как на 512 байт ОЗУ контролировать ресурсы(тот-же stack) в крупном проекте? Да никак, поэтому вы все на Си и на STM где больше ресурсов. Потому что тупо не можете. А я вот например могу на Cortex асме писать код для STM и периферию я их гораздо лучше понял взявшись за асм после Си.

Четвертое - трудозатратно. Не особо, возможно на багфиксинг утечек памяти на Си вы потратите не намного меньше времени, чем я на реализацию на асме. Здесь ключевое - наработки - сообщество Си наработало огромный пласт кода, и вы не задумываясь его используете считая свой код основными трудозатратами. При этом говоря про асм все почему-то думают о пустом листе, на котором все, все, все нужно писать с нуля. С чего бы? Переносимость? Об этом ниже. На асм можно точно также наработать(и это было ранее) все теже функции, что и вы используете в Си. Но нет, популяризация Си свела на нет наработки на асм.

Пятое - переносимость кода, да это главный минус в асм. Однако умение строить алгоритмы существенно снижает трудозатраты. Так же как и разделение кода на уровни. Я лично наработал операционку с кучей функций, я не пишу математику и другие процедуры с нуля, я их просто подключаю и вызываю также как это делаете вы в Си. Более того, мой код(особенно код верхнего уровня) без проблем переносится между МК семейства AVR. И потом, как вы вообще представляете перенос сложной программы на Си с AVR скажем на STM, да никак. Где ваша хваленая переносимость Си?

Если мне нужно что-то по быстрому накидать для периферии - я возьму микрокомпьютер и за минуты накидаю на Java то, на что вы потратите в несколкьо раз больше времени на Си.

Если мне нужна сложная логика - я не буду это делать на микроконтроллере, я возьму что-то типа SoC или опять же микрокопьютер.

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

Я не вижу по большей части где и для чего использовать Си. Это просто мода.

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

А если мне нужно будет говнокодить, с целью быстренько что-то где-то копипастить и выдать за свое решение, срубить бабла по бытрому, тогда да, я возьму STM и буду писать на Си. Но мне такая работа не интересна.

Умный дом

214 постов2.5K подписчиков

Вы смотрите срез комментариев. Показать все
1
Автор поста оценил этот комментарий

Одно из преимуществ С/С++ как раз в том, что код можно собрать на "любой" платформе и пользоваться им, например, алгоритмы или протоколы связи. При этом у вас имеется множество механизмов для отладки и тестирования кода.

Перенос кода между МК и даже запуска на ПК, если это изначально задумывалось, выливается в реализацию отдельных функций/методов работы с периферией.
Как отличается работа с периферией на AVR в случае ассемблера и C вообще понять не могу. Суть же одна и та же, работа с регистрами.

раскрыть ветку (10)
Автор поста оценил этот комментарий

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


Да, с AVR сдесь отличий мало, тем не менее работы с указателями, как бы многим не казалась, ее нет в асемблере - есть незамутненая, элементарная работа с памятью. Здесь конечно лучше говорить предметно, но мне сложно будет прямо сейчас подобрать примеры. Может быть потом.

раскрыть ветку (9)
2
Автор поста оценил этот комментарий

Основной код программы это работа с периферией? Это ножкой подрыгать или таймер запустить?
Вы пошутили? Или действительно верите, что перенести проект, например, с AVR на STM32, будет одинаково по сложности в случае ассемблера и С?
В каком протоколе необходима выдержка конкретного количества тактов?

раскрыть ветку (8)
Автор поста оценил этот комментарий

Да, работы с переферией, UART, 1Wire, GPIO, таймеры и т.п. прсото сделано все по уму, без кишков наружу.

Да, хороший большой проект будет очень сложно перенести с AVR на STM32(не важно си это или ассемблер), а c STM32 на AVR скорее всего вообще невозможно. Более того, я такую процедуру делал, частично перенес свою ос на STM32.


:D Попробуйте сами перенести именно реалтайм ОС(а не программу ее использующую) с AVR на STM32.


Напрмер, с программнй реализацией UART на больших баудрейтах ;) или некоторые реализации железа на SPI

раскрыть ветку (7)
3
Автор поста оценил этот комментарий

UART - это интерфейс, а не протокол. То же самое касается SPI.

Необходимость ОС в AVR, на мой взгляд, вообще под большим вопросом, ни разу не встречал необходимость в ней. Но, например, FreeRTOS может работать и на Mega.

раскрыть ветку (6)
Автор поста оценил этот комментарий

Не лучший пример - хорошо, любой протокол где нужно выдерживать тайминги на высоких скоростях передачи данных. так лучше?


Необходимость - это уже другой вопрос, я например не вижу необходимости переноса проектов с AVR на STM.

раскрыть ветку (5)
2
Автор поста оценил этот комментарий

Дак вы пример протокола приведите. Лично я такой не встречал.
STM как пример, это может быть, например, PIC или MSP. А смена используемого МК не редкость, а тем более повторное использование кода в другом проекте.

раскрыть ветку (4)
Автор поста оценил этот комментарий

Ладно хорошо, что насчет программной реализации сетевых уровней CAN?

раскрыть ветку (3)
0
Автор поста оценил этот комментарий

Понятия не имею. Что с ними?.
Посмотрите библиотеку V-USB, хороший пример связки С и ассемблера.

раскрыть ветку (2)
Автор поста оценил этот комментарий

Ну Вы же пример просили привести. Вот, пожалуйтса.


И вообще мы играем в какую-то странную игру, вы ставите мне условие котрые максимально удобны для вас. А чем Вам в принципе не угодили интерфейсы? Ситуация где нужно считать такты как раз часто встречается как раз в программной реализации интерфейсов типа SPI, UART, USB, CAN. Именно здесь и есть преимущество ассемлера.

И потом протокол - это набор соглашений интерфейса логического уровня. Подобные соглагения используются как минимум в UART, USB и CAN.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Пример какой? Что в CAN требует использования ассемблера?
Программная реализация интерфейсов, скорее всего, выльется в несколько платформенно-зависимых функций, пусть даже написанных на ассемблере. Основной код вообще не должен знать с каким интерфейсом работает: аппаратным или программным.

Вы смотрите срез комментариев. Чтобы написать комментарий, перейдите к общему списку