Делай хорошо, плохо само получится


Поводом к посту послужила недавняя (когда я начинал писать этот пост, она действительно была недавней, но что-то пост долго пролежал в папке Неоконченное) публикация на Хабре относительно аспектов реализации программного UART на МК фирмы AVR. Сами по себе поднятые вопросы небезынтересны, но даны на них столь странные ответы, что посчитал своим долгом внести необходимые разъяснения. Тема обозначена, те, кто захочет прочитать о «королях, капусте и башмаках», то есть требованиях стандартов, чтении (правильном) технической документации и рекордах в программировании на ассемблере для AVR, могут нажать на кнопочку ниже.

Обозначим вопрос более подробно — возможна ли реализация ИРПС (привычное мне название интерфейса, в девичестве имеющего имя UART) на МК типа AVR ( конкретно речь шла о Tiny13) при работе от внутреннего генератора. Дело в том, что данный генератор имеет не слишком хорошие показатели по точности удержания частоты, почему данный вопрос и возникает. Сразу оговорюсь, что не имеет значения, будем ли мы рассматривать программную реализацию (как было предложено в исходном посте) либо использовать аппаратные блоки МК. Результаты одного способа (в части точностных параметров по времени) практически полностью транслируются на другой.

Принципиальным является вопрос о том, может ли внутренний генератор обеспечить требуемую точность функционирования, так как в случае отрицательного ответа на этот вопрос дальнейшие исследования становятся бессмысленными. Для сравнения двух независимых величин нам необходимо знать их обе, поэтому начнем с определения требуемой точности удержания частоты и предоставляемых данным конкретным МК возможностями в данной части. Важное замечание к предыдущему предложению — имеется в виду отнюдь не конкретный экземпляр, «данный нам в ощущениях», а конкретный тип МК, который представлен своим техническим описанием.

Для начала найдем то, что найти проще (ну, я так думал) — требования к точности временных параметров интерфейса. Откроем стандарт на RS232 и все нужное сразу увидим. Оказалось, что «нельзя просто так взять и ...», поскольку стандарт является платным и все лежащие в Сети копии нелегальны. Ладно, берем отечественную версию ГОСТ на стык С2 и не обнаруживаем там вообще никаких временных параметров, за исключением длительности фронта и среза импульса. Поначалу это вызвало легкую оторопь — как так может быть — но потом пришло понимание, что стык С2 описывает только интерфейсную часть ИРПС и требования должны заключаться именно в последнем. В принципе, все логично, непонятно только, почему в ГОСТ это явно не описано, но, в конце концов, иногда можно и подумать самому, хотя все равно «как то не аккуратненько получается».

Конечно, зная протокол передачи, можно из общих соображений найти максимально допустимое рассогласование скоростей передатчика и приемника (0.5/9.5=5.2%), но это будет исследование сферического коня сами знаете где, поскольку:

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

Странствия по просторам Инета привели на AppNote от Atmel (ну раз мы все равно используем МК этой фирмы), где прямо говорится о допустимом рассогласовании в 2% с равным бюджетом, что приводит к требования точности поддержания частоты передатчика в 1%. Поверим уважаемой фирме и предположим, что они имеют доступ к секретным материалам и эта цифра верна, тем более, что выглядит она правдоподобно. Понимаю уязвимость подобной позиции, но мне, честно говоря, надоело искать точный ответ на такой простой вопрос, и не терпится перейти к следующей части.

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

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

Так что открываем документацию (Вы можете открыть файл в просмотрщике, а у меня есть типографская версия описания, отпечатанная самой фирмой-производителем — да, раньше такое бывало) и ищем соответствующий раздел. Интересующие нас параметры находятся в разделе «Calibrated Internal RC Oscillator», далее при необходимости идем по ссылкам. И вот тут нас (меня точно, насчет Вас не уверен) ждало первое разочарование — я давно (лет 15) работаю с продукцией Atmel, и всегда считал, что у них хорошая документация на МК. Как утверждают психиатры, «нет здоровых людей, есть не дообследованные» и внимательное изучение соответствующего раздела подтвердило эту истину, как я мог раньше не замечать таких провалов в документации. В свое оправдание могу только сказать, что:

  1. я никогда не использовал в данных МК внутренний генератор, поэтому особенно внимательно его не изучал;
  2. когда я начинал работать с этими МК (намного больше 10 лет назад) я был молодой (ну точно моложе, чем сейчас) и глупый и не понимал в должной степени необходимости хорошей (понятной, исчерпывающей и однозначной) документации;
  3. я готов себя многое простить, просто потому, что я себе многое прощаю, и все мои недостатки не фатальные (последний аргумент особенно убедителен, не правда ли).

Так вот, закончив посыпать свою голову пеплом, начну излагать свои претензии к документации и тут никаких оправданий фирме-изготовителю быть не может. Открываем вышеуказанный раздел и начинаем его внимательно изучать, переходя при необходимости на нужные страницы (Вы по-прежнему кликаете на ссылки). Мы вместе будем искать следующие параметры, характеризующие временные характеристики генератора: номинальная точность, влияние напряжения питания, влияние температуры и параметры старения — это минимально необходимый набор для оценки точностных параметров любого генератора.

Первая часть марлезонского балета-номинальная точность.

Сразу же находим нужный параметр — таблицу точности настройки генератора, в которой видим две строки «Factory Calibrated» с указанным значением ±10% и «Manual Calibrating» с аналогичным параметром ±2%.

По поводу этих данных сразу возникает ряд вопросов — что они означают и как проводятся измерения данного параметра. Для первой строки в самой таблице указаны температура (окружающей среды или самого МК — неясно, но это уже капризы с моей стороны) и напряжение питания, кроме того, в примечании сказано (на мой взгляд, излишне) что данное измерение проводится в конкретной точке пространства внешних условий. Можно догадаться, что при этом мы должны использовать записанный на предприятии-изготовителе калибровочный коэффициент, хотя вот это как раз лучше было бы явно указать в примечании. Все более-менее ясно и интерпретируется почти однозначно (хотя в разрезе исследования технической документации следовало бы сказать, что все нечетко и допускает вариации в трактовках, и это недопустимо, но если мы так сделаем, то тема дальнейшего обсуждения просто исчезает (и о чем дальше писать, непонятно, поэтому проявим снисходительность).

А вот со второй строкой дела похуже — даны пределы изменения температуры и напряжения питания и утверждается, что применением некоей волшебной процедуры калибровки можно достичь существенно лучшего, нежели заводской, результата во всем диапазоне. У меня сразу же возникает вопрос — если этого можно добиться повсюду (в любой точке температуры и питания) и фирма-изготовитель знает, как это сделать, то почему она это не сделала сама при фабричной калибровке в конкретной точке условий? Обращаемся к описанию калибровочного байта и видим, что он принимает 128 значений и и этом перекрывает диапазон от 50% до 200% номинала, что соответствует 150/128~1.17% изменения частоты на единицу значения калибровки, что должно дать ожидаемую точность лучше, чем в 1%. Но дальше нам следует учесть, что регулировочная характеристика явно не линейна и в области больших значений калибровки имеем 60%/32~2% шага (данные взяты с графика, я неоднократно высказывал свое отношение к подобному методу представления технических параметров, но повторюсь — это неприемлемый метод, хотя, конечно, лучше, чем ничего), что дает точность в 1% и если мы учтем не монотонность регулировочной характеристики (да, именно так указано в документации, не нарисовано в графике, а явно указано в тексте. Я категорически отказываюсь понимать как, и главное зачем, фирма захотела сделать именно такой закон регулировки, но ей удалось), что явно указано в рекомендациях, то следует считать точность в 2% вполне достижимой. Мне не очень нравится, что пришлось смотреть график, но это не обязательно и табличные данные являются достаточными. В данной части следует считать документацию вполне понятной и непротиворечивой, критерий правильности лежит вне пределов нашей компетенции.

Вторая часть марлезонского балета. — влияние внешних условий.

А вот дальше начинается «трэш, угар и содомия». Вместо таблиц значений нам предлагается смотреть картинки (в документации они почему то называются графиками типовых значений), а, как известно, «главное преимущество графического представления информации — его наглядность, и других преимуществ у него нет». Можно было бы пользоваться даже такой информацией и с графика снять граничные значения («хотя это и оскорбительно для коллектива»), если бы данный график не приводился в разделе «Typical Characteristics». Не знаю, как кто, лично я глубоко убежден, что указать типичные (или типовые, не знаю, как правильнее, в одном фильме говорили «типическая внешность») значения, хоть в виде графика, хоть в таблице — это не указать просто ничего. На них нельзя ориентироваться при проектировании, поскольку эти параметры непонятно что означают и любое отклонение значений от типовых допустимо, в отличие от минимальных и максимальных значений, переход которых означает неисправность устройства.

Ладно, проехали, попытаемся извлечь хоть какую-то информацию и видим, что при изменении температуры от -40 до +80°С частота генератора изменяется на ±4%. Аналогичная картина и с напряжением питания — только типовые графики и результирующая погрешности в -6 +2% от 3.3 до 5.5. Данных же по старению генератора просто не дают, что, в общем, логично, поскольку на фоне уже приведенных параметров точность в единицу процента за 5 лет (характерная величина для кремния) уже никого не волнует.

Теперь у нас есть все данные для ответа на наш изначальный вопрос — при фабричной калибровке генератор не отвечает требованиям интерфейса по точности, при калибровке под конкретные условия применения — отвечает граничным требованиям, но не отвечает стандарту. Следует также учесть, что если калибровку под напряжение питания и конкретный МК можно сделать при изготовлении устройства и надеяться, что они не изменятся во времени, то учет температуры возможен только «на лету» и требует внешнего эталона времени соответствующей точности. Поскольку при разработке устройств следует руководствоваться правилом «в Бога мы верим, все остальное требует доказательств», а возможность соответствия требованиям мы не доказали, то правильный ответ — гарантировать реализацию ИРПС, отвечающего требованиям стандарта, в данном МК с внутренним генератором невозможно. Обратим внимание, что приведенный вывод мы сделали при анализе документации и сформулировали именно таким способом, чтобы подчеркнуть, что на конкретном экземпляре МК все может и получиться, если звезды встанут удачно. То есть наш вывод противоречит ранее упомянутому посту, как могло такое получится, ведь у человека все замечательно работает — давайте разбираться.

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

  1. Хороший способ — измерить критичные параметры интерфейса устройства и сравнить их с требованиями стандарта — это можно сделать с помощью универсальных приборов (в нашем случае осциллограф и длина битового интервала либо полной посылки), либо с помощью специализированного прибора, который сертифицирован на выполнение проверки данного интерфейса.
  2. Так себе способ — организовать взаимодействие с другим устройством, которое реализует ответную часть интерфейса и является доказанным (отвечает требованиям стандарта). Конечно, такая проверка совершенно недостаточна, и скорее, может быть применена более для подтверждения неисправности тестируемого устройства, но делает хоть что-то.
  3. Плохой способ — самостоятельно реализовать ответную часть интерфейса (в этом же устройстве или в ином) и взаимодействовать с ней. Поскольку оба устройства очевидно не доказаны, то польза от подобной проверки весьма и весьма сомнительно. Хорошим примером такого подхода является «эхо» на последовательном канале, которое ничего, кроме того факта, что устройство в принципе не сломано и способно что-то как-то передать, не доказывает и о скорости передачи сообщает ненамного больше, чем ничего.
  4. Ужасный способ — взять в качестве тестирующего вообще не отвечающее требованиям стандарта (а лучше противоречащее им) устройство и работать, как в предыдущем пункте.

Именно последний способ применен в рассматриваемом посте — реализуется программный приемник последовательного канала, который, в противоречие с требованиями стандарта, изменяет свою частоту, подстраиваясь под входной сигнал (конкретно под длину стартового бита), что позволяет устойчиво принимать сигнал плохого качества в смысле временных параметров. Нельзя сказать, что так делать не следует никогда, более того, в аналоговых модемах была принята настройка на входящую скорость, которая реализовывалась аналогичным образом, но это было именно переключение частоты путем изменения делителя, и явно не наш случай. И именно в таком варианте все великолепно получается и информация передается устойчиво при любых внешних условиях. Поэтому, если говорить о возможности передачи информации между двумя МК, работающими от внутренних генераторов, с использованием интерфейса, отдаленно напоминающего ИРПС, то ответ положительный. Если же речь идет о взаимодействии с внешними устройствами, отвечающими требованиям стандарта и ничему более, то нас будет ожидать множество неприятнейших сюрпризов.

Общий вывод из вышесказанного:

  1. при проектировании устройств следует обращать основное внимание на документацию (RTFM),
  2. необходимо изучать документацию и правильно интерпретировать прочитанное (RTFMF),
  3. иметь в виду, что в документации в наше время могут быть недоговоренности, неточности (и даже ошибки), поэтому
  4. проверять полученную информацию на непротиворечивость и правдоподобность, и
  5. использовать экспериментально полученную информацию только для подтверждения полученных из анализа документации выводов, при этом
  6. особо тщательно выбирать методы экспериментов по тестированию аппаратуры для получения достоверного результата.

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

.equ delay=15
TX_Byte:
	cli
;	ld 	r18,Z+
;	cp 	r18,r1
;	breq	Exit_Transmit
;	dec 	r1
	cbi 	port, TX_line
Delay_TX:
	ldi 	r16,delay
Do_Delay_TX:
	nop
	dec 	r16
	brne	Do_Delay_TX	
TX_Bit:
	sbrc 	r18,0
	sbi 	port,TX_line
	sbrs	r18,0
	cbi 	port,TX_line
	lsr	r18
	lsr	r17
	brcs	Delay_TX
	sbi	port,	TX_line
	ldi	r16,delay
Stop_Bit_TX:
	nop
	dec	r16
	brne	Stop_Bit_TX
	Sei

И сразу в глаза бросается ошибка в программе — в строке 3 (закоментированна) значение регистра 1 должно быть нулевым, но явно в функции присвоение не прописано. После выполнения цикла передачи одного байта данное значение гарантируется строкой 12, но при первом проходе — нет. Поэтому должна быть добавлена инициализация, что потребует увеличения размера кода.

Второй недостаток — собственно формирование уровня в строках 4-7, поскольку принятая автором методика выдачи очередного бита приведет к джитированию фронта на 2 такта при различных переходах (0-1 и 1-0), что повлечет за собой повышение требований к точности удержания частоты. Не то, чтобы это давало очень сильное влияние, но, если можно исправить недостаток, не удлиняя программу, то почему бы и нет — смотри эпиграф. Первоначальный вариант занимал 4 слова и исполнялся за 4 такта, новый занимает 4 слова и исполняется за те же 4 такта. Да, исправленный вариант требует более глубокого изучения архитектуры МК, но кто говорил, что будет легко. С другой стороны, в первом варианте модификация порта атомарна, а во втором — нет, в данном случае это неважно (мы явно запретили прерывания), но осадок остается. Если бы в рассматриваемом МК был настоящий битовый процессор, как в архитектуре 51, то мы могли бы написать идеальный фрагмент, сочетающий все преимущества обоих подходов (и даже был бы чуть короче), но что мечтать о несбыточном…

Третий недостаток — вопрос более стиля. Я неоднократно высказывал свое отношение к магическим константам, которые мы видим в преамбуле данной программы. Еще раз подчеркну — от того, что автор задает константу в преамбуле программы, а не непосредственно в операторе, «обычная уличная магия» никуда не девается. Дело в том, что мы должны явно предъявить читателю метод формирования конкретного значения, а не создать синоним для значения, полученного неизвестным путем. Можно, конечно, написать комментарий к строке со значением, в котором указать расчетную формулу, но лучше явно использовать расчетную формулу при формировании константы и тогда комментарий просто не понадобится (разумеется, при говорящих именах применяемых констант). Так и сделано в нижеприведенном тексте, причем обратите внимание, что мы проводим преобразование в целое число только в последний момент и правильно округляем, что позволяет не потерять точность результата.

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

Ну а теперь, когда мы исправили ошибки (кроме последней), попробуем программу улучшить в смысле главного критерия (для достижения рекорда, в данном конкретно случае) — длины кода. Первое, что бросается в глаза — наличие двух выдержек времени, что плохо, поскольку нарушает принцип DRY (общее требование) и увеличивает размер кода (конкретное требование). Можно было бы оформить данный фрагмент в виде подпрограммы и мы все равно выиграли бы по длине, поскольку добавляем мы 3 слова кода (по 1 для вызова в двух местах и 1 для возврата), а экономим 4, но есть значительно более красивый путь — аккуратная организация цикла передачи байта, которую можно видеть в следующем тексте.

.equ delay=15
TX_Byte:
	cli
	sec		; потребуется для стоп-бита
	clt		; устанавливаем старт-бит
TransBit:		; собственно формирование бита
	in 	r17,port
	bld 	r17,Tx_line
	out 	port,r17
Delay_TX:		; формируем длину битового интервала
	ldi 	r17,delay
Do_Delay_TX:
	nop
	dec 	r17
	brne	Do_Delay_TX	
TX_Bit:
	bst 	r16,0
	ror	r16
	clc		
	brne  TransBit ; есть что передавать
	brcs	TransBit ; передаем стоп-бит
Exit_Transmit:
	Sei

Обратим внимание, как мы используем передаваемый байт совместно с битом переноса в качестве счетчика битов, красивое решение, но обладает одним недостатком — длительность последнего бита данных будет несколько (на 2 такта) длиннее остальных, за счет задержки перехода. Если бы речь шла о стоповом бите, то «наплевать и забыть», поскольку минимальный интервал между передачами нам не задан, но это значащий бит, да мы еще только что критиковали исходную программу за подобное поведение. Не будем уподобляться библейскому персонажу из притчи о соринке в чужом глазу и примем меры к устранению. Данное явление легко можно было бы компенсировать введением задержки на 2 такта, но увеличится длина кода, а это ключевой параметр. Поэтому пойдем классическим путем и поменяем время на память — используем отдельный регистр для организации счетчика передаваемых битов, и получим совершенно одинаковые битовые интервалы при том же размере кода.

Следующее улучшение связано с формированием длительности битового интервала, которое в исходной программе выполняется на 4х тактовом цикле. Если мы сделаем его 3х тактовым (минимально возможным в данном МК), то сможем сэкономить один байт кода и потенциально можем улучшить точностные параметры, поскольку дискретность задержки станет меньше (отклонение не превосходит половины размера дискрета при правильном округлении). Но следует иметь в виду, что в конкретном случае мы можем и потерять точность, все зависит от исходных данных. Еще одно обстоятельство, которое могло повлиять на выбор именно такой длительности цикла — максимальный размер задержки при байтовом счетчике составляет 256 значений — для имеющегося варианта можно использовать скорости от 9600 бод и выше, а вот с 3х цикловой задержкой это невозможно. Было бы весьма неплохо отразить данное обстоятельство (минимально допустимая скорость порта) в комментариях к программе и заодно вывести предупреждающее сообщение в случае нарушения данного требования. Ну и внести соответствующие модификации в макросы формирования параметра для формирования задержки, не забывая использовать «говорящие» имена для обозначения переменных.

.equ Freq = 8000000
.equ BaudRate = 115200
.equ PayLoad = 9  ; количество тактов вне цикла
.equ CycleTime = 3 ;количество тактов в цикле
.equ delay=((Freq*2/BaudRate - PayLoad*2)+CycleTime)/(CycleTime*2)
TX_Byte:
	cli
	ldi r18,10
	sec		; потребуется для стоп-бита
	clt		; устанавливаем старт-бит
TransBit:
	in 	r17,port
	bld 	r17,Tx_line
	out 	port,r17
Delay_TX:
	ldi 	r17,delay
Do_Delay_TX:
	dec 	r17
	brne	Do_Delay_TX	
TX_Bit:
	bst 	r16,0
	ror	r16
	dec r18
	brne	TransBit
Exit_Transmit:
	sei

Теперь посмотрим на результат — размер кода уменьшился с 20 до 16 слов (если учитывать только собственно передачу, то еще более разительно — с 18 до 14, джиттер фронтов исчез (конечно, только та компонента джиттера, которая обусловлена особенностями программы, на аппаратную составляющую мы не посягаем), точность выдерживания временных интервалов улучшилась, программа стала нагляднее и проще в понимании (за счет комментариев, поскольку даже хорошо написанная программа на ассемблере само-документируемой, как правило, не является).

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

Ну и в заключение — задача написания кода минимального размера в наше время выглядит несколько надуманной, но, совершенно неожиданно, получает подтверждение своей жизненности. В конце прошлого года (2016, вот как долго ждал своей очереди этот пост) анонсирован новый МК из семейства MSP430, который наряду с уникально низкой ценой (26 центов — ждем появления китайских устройств на его основе) имеет и уникально малый размер памяти программ — 512 байт (нет, я не ошибся, буквы «к» сразу после цифры нет). Так что размер кода может оказаться критичным при использовании данного прибора, да и вообще написание подобных экстремальных программ требует углубленного изучения МК, а «труд уже сам по себе есть благо».

Комментарии (17)


  1. amartology
    01.06.2018 18:39
    +3

    поскольку задача формирования в интегральном исполнении точного конденсатора, да и точного резистора, весьма нетривиальна

    Она не «нетривиальна», она принципиально не решаема без внешней подстройки. Точно можно делать только согласованные пары, а именно номинал точно задать нереально, и чем тоньше техпроцесс, тем хуже.
    Собственно, вся современная (да и несовременная) аналоговая схемотехника строится на том, чтобы от номиналов компонентов ничего не зависело, только от их соотношений между собой.
    Либо, там, где точное значение все-таки важно (например, в источниках опорного напряжения или генераторах частоты), используется внешняя подстройка конкретного экземляра. Раньше лазером подпиливали резисторы, сейчас все больше подстроечную однократно программируемую память используют.


  1. Amomum
    01.06.2018 20:37

    Шел 2018 год, а люди все еще программировали AVR на ассемблере.


    1. jaiprakash
      01.06.2018 22:27
      +1

      И в 2028 будут писать на ассемблере и на AVR, и на x86.
      Можете скринить.


    1. soshnikov
      01.06.2018 22:28
      -1

      Вы находите в этом нечто противоестественное?


      1. Amomum
        02.06.2018 00:10
        +1

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

        Но если AVR (и особенно ассемблер) тащат в продакшен просто по привычке, то таки да, нахожу. Я уже достаточно страдал из-за людей, которые пишут километровые ассемблерные программы без единого комментария и потом сами в них ничего найти не могут; используют процы без отладочного разъема, которые каждый раз выпаивать нужно, чтобы прошить; добровольно используют архитектуры, для которых есть только компилятор С89, да еще не полностью поддерживающий стандарт и тому подобное.

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

        Как-то так.


        1. 0xd34df00d
          02.06.2018 03:52

          Упихивал код на плюсах с темплейтами в сотни байт на аттини, не вижу проблем.


          1. monah_tuk
            03.06.2018 04:47

            Темплейты вообще огонь. Делал абстракцию для типобезопасного доступа к регистрами I2C, по сути формальное описание, к какому устройству относится, какие биты для доступа, что в них лежит и как интерпретировать, дать по рукам на этапе компиляции, если пытаешься писать не то, что ожидается и так далее. В рантайме от этого вообще ничего не осталось, только финальный доступ к функциям вида i2c_read(dev, buf, len)/i2c_write(dev,buf,len).


            1. den_po
              03.06.2018 17:30

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


              1. monah_tuk
                04.06.2018 05:28

                обычный " -O2", я как-то наловчился с JTAG на этом отлаживаться. У меня работа с USB, реализация UVC и UAC классов устройства, боюсь писать проект, который бы запускался на Linux и/или Windows, это +ровно столько же времени, сколько делали продукт, а то и больше.


  1. jaiprakash
    01.06.2018 20:42

    В AVR GCC регистр r1==0, он выставляется в стартовом коде, а когда он используется, например, для умножения, то после немедленно обнуляется. Сейчас не помню, возможно, оно вместе оформляется как атомарная операция.


  1. the_turkale_cat
    02.06.2018 08:04

    Во время бурной молодости нужно было быстро сделать прибор для подачи команд световым приборам по DMX. Из приборов и материалов был PIC16F628 в дипе, 75176, горка конденсаторов и оторванная откуда-то клавиатура матричная ну и шайба вторая (ICD2).
    Кварцевого резонатора не было и ехать за деталями не хотелось.
    В итоге получилось передать битрейт 250k при скорости работы микроконтроллера 1 MIPS, правда, лапку, на которую выводится TX, пришлось выбирать либо 0, либо 7 бит любого порта, но уж это мне было не особо критично.

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


  1. alex_kag
    02.06.2018 08:54

    А меня вот зацепило использование слова ИРПС. ИРПС — это интерфейс токовая петля. И называть так UART, мне кажется, не правильно…


    1. Serge78rus
      02.06.2018 11:31

      Это лайфхак такой, позволяющий сократить количество переключений раскладки клавиатуры.

      Это была шутка. Разумеется, Вы правы.


    1. juray
      02.06.2018 13:55

      Угу. Так же, как и приравнивать UART к RS-232C (стык С2).
      UART на выводах микроконтроллеров — это другой физический уровень.

      А ИРПС был описан вообще в ОСТ 11 305.916-84. Только его теперь фиг найдёшь — остались одни упоминания. Там физический уровень да, токовая петля.

      Но формат посылки у них общий (а также для RS-485, RS-422, ISO 9141/ISO-14230 и еще кучи), так что и временные параметры посылки тоже должны быть общими. Вопрос — куда запихали это описание. По-хорошему, на это должен быть отдельный стандарт.

      Тот же ОСТ 11 305.916-84 волне мог содержать и описание посылки. Но мне думается, это должен быть ГОСТ.


  1. Serge78rus
    02.06.2018 11:19

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


  1. DuMOHsmol
    02.06.2018 13:36

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


  1. juray
    02.06.2018 14:03
    +1

    берем отечественную версию ГОСТ на стык С2 и не обнаруживаем там вообще никаких временных параметров, за исключением длительности фронта и среза импульса

    А вы какой ГОСТ смотрели? Судя по всему — старый советский ГОСТ 23675-79 (про физический уровень), а не ГОСТ Р 50668-94 (про временные характеристики)?
    В 50668 вполне есть «Требования к временным характеристикам сигналов данных передающего ООД»:
    image
    и есть «временные характеристики качества работы ООД, принимающего сигналы данных по цепи 104»