All posts by DI HALT

Прошивка PinboardProg для превращения демоплаты PinBoard 1.0 в ISP программатор

Хай Pinboard сообщество! Помнится я обещал, что будет прошивка позволяющая превратить демоплату Pinboard 1.0 в программатор для прошивки других МК. Пацан сказал — пацан сделал :)
 

Итак, вот две прошивки. Для плат на базе Atmega16 и Atmega32. Тактовая 8 МГц (дефолтная настройка).
16_PinboardPROG.hex
32_PinboardPROG.hex

 

Далее как обычно в картинках. (далее…)

Read More »

AVR. Учебный Курс. Использование Bootloader’а

Почти все микроконтроллеры серии Mega с памятью от 8КБ могут прошиваться через бутлоадер. Фишка удобная и применяется довольно часто, однако подробного мануала как работать с бутлоадером на AVR я в свое время не нашел и пришлось разбираться самостоятельно. С той поры мало что изменилось. Пора бы дать подробное описание как выбрать, скомпилировать, прошить и в дальнейшем использовать bootloader для AVR.
 

Ликбез
Что же это такое бут и с чем его едят. BootLoader это всего лишь небольшая программка которая сидит в специальной области памяти микроконтроллера и слушает какой-либо интерфейс. Обычно это UART, но бывает и SPI, USB и даже SoftUSB бутлоадеры.
 

При загрузке контроллера управление первым делом передается бутлоадеру и он проверяет есть ли условие для запуска. Условие может быть любым, но обычно это либо наличие спец байта по интерфейсу, либо наличие нужного логического уровня на выбранной ножке контроллера, сигнализирующее о том, что мы хотим обратиться к буту прошивку. Если условие есть — то бутлоадер может, например, принять прошивку по UART‘у и сам прошить ее во флеш. Или, наоборот, считать прошивку из флеша и выдать через UART, считать или записать EEPROM, подрыгать ножками. Да что угодно. Но обычно все же с помощью бута осуществляют прошивку микроконтроллера без применения спец программатора.
 

Если разрешающего условия при старте нет, то бут завершает свою работу и передает управление основной программе.
 

(далее…)

Read More »

SinaProg — графическая оболочка для AVRDude

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

С одной стороны это хорошо — консольная утилита позволяет очень сильно ускорить и автоматизировать процесс прошивки. Один раз написал батничек и для перешивки только вызывать его и все.

Остается проблема прошивки разных устройств, ведь под каждую придется делать свой батник. И ладно бы ключи прописать, да файл с прошивкой указать. Самая засада начинается с fuse битами (впрочем, как и везде в мире AVR ;) ) Тут их надо вначале внимательно проштудировать в даташите, выписать в виде байтов, вписать правильно в командную строку и молиться на то, чтобы нигде не ошибиться.
Да, для avrdude написано много оболочек, но все что мне встречались раньше решали лишь малозначительную проблему выбора нужного ключа файла и/или программатора, а фузы также было надо указывать числом.

Проблема решилась с появлением новой версии оболочки SinaProg от команды программистов-террористов из Аль-каиды иранских AVR программеров.

Запускаем… Если не запустилась, то возможно потребуется установить фреймворк от NI — LabView RunTime Library

(далее…)

Read More »

Конденсатор и RC цепочка

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

О многочисленных способах применения которой я сегодня и решил рассказать. Но вначале про каждый элемент в отдельности:
 

Резистор — его задача ограничивать ток. Это статичный элемент, чье сопротивление не меняется, про тепловые погрешности сейчас не говорим — они не слишком велики. Ток через резистор определяется законом ома — I=U/R, где U напряжение на выводах резистора, R — его сопротивление.
 

Конденсатор штука поинтересней. У него есть интересное свойство — когда он разряжен то ведет себя почти как короткое замыкание — ток через него течет без ограничений, устремляясь в бесконечность. А напряжение на нем стремится к нулю. Когда же он заряжен, то становится как обрыв и ток через него течь перестает, а напряжение на нем становится равным заряжающему источнику. Получается интересная зависимость — есть ток, нет напряжения, есть напряжение — нет тока.
 

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

Read More »

Программатор Громова

Самый простой вариант программатора для AVR это пять проводков, припаиваемых к порту контроллера и втыкаемых в LPT порт. Не спорю, можно и так. Но я все же не рекомендую этот способ. Даже схему подключения давать не буду — если надо будет сам найдешь. Так как данный метод не очень стабилен, возможны сбои при прошивке, длина проводков ограничена двадцатью сантиметрами (если больше, то будет глючить), поэтому придется шариться в комповой заднице. Да и LPT порт спалить проще простого. В общем не рулез.

Шарясь по инету, я нашел отличный программатор, работающий через RS232 он же COM порт. А также удобную программу для прошивки контроллера UniProf от Николаева. Схему программатора придумал Громов, создатель Algorithm Builder.

Саму программу UniProf можно скачать у меня, но лучше взять с сайта автора. Возможно там будет версия посвежее.
(далее…)

Read More »

AVR. Учебный курс. Трактат о программаторах

Программа для микроконтроллера пишется на любом удобном языке программирования, компилируется в бинарный файл (или файл формата intel HEX) и заливается в микроконтроллер посредством программатора.
 

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

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

Программаторы бывают разные под разные семейства контроллеров существуют свои программаторы. Впрочем, бывают и универсальные. Более того, даже ту же простейшую AVR’ку можно прошить несколькими способами:
 

Внутрисхемное программирование (ISP)
Самый популярный способ прошивать современные контроллеры. Внутрисхемным данный метод называется потому, что микроконтроллер в этот момент находится в схеме целевого устройства — он может быть даже наглухо туда впаян. Для нужд программатора в этом случае выделяется несколько выводов контроллера (обычно 3..5 в зависимости от контроллера).

(далее…)

Read More »

Подключение микроконтроллера. Ликбез.

Казалось бы простая тема, а однако в комментах меня завалили вопросами как подключить микроконтроллер. Как подключить к нему светодиод, кнопку, питание. Что делать с AGND или AREF. Зачем нужен AVCC и все в таком духе. Итак, раз есть вопросы, значит тема не понятна и надо дать по возможности исчерпывающий ответ. Все описываю для контроллеров AVR, но для каких нибудь PIC все очень и очень похоже. Т.к. принципы тут едины.
 

Чтобы понимать ряд терминов активно упоминающихся в этой статье, надо сначала прочитать статью про порты ввода-вывода.

 

Питание
Для работы микроконтроллеру нужна энергия — электричество. Для этого на него естественно нужно завести питалово. Напряжение питание у МК Atmel AVR разнится от 1.8 до 5 вольт, в зависимости от серии и модели. Все AVR могут работать от 5 вольт (если есть чисто низковольтные серии, то просьба уточнить в комментах, т.к. я таких не встречал). Так что будем считать что напряжение питания контроллера у нас всегда 5 вольт или около того. Плюс напряжения питания обычно обозначается как Vcc. Нулевой вывод (а также Земля, Корпус, да как только его не называют) обозначают GND. Если взять за пример комповый блок питания. То черный провод это GND (кстати, земляной провод традиционно окрашивают в черный цвет), а красный это +5, будет нашим Vcc. Если ты собираешься запитать микроконтроллер от батареек, то минус батареек примем за GND, а плюс за Vcc (главное чтобы напряжение питания с батарей было в заданных пределах для данного МК, позырь в даташите. Параметр обычно написан на первой странице в общем описании фич:
 

• Operating Voltages
–1.8 — 5.5V (ATtiny2313V)
–2.7 — 5.5V (ATtiny2313)
• Speed Grades
–ATtiny2313V: 0 — 4 MHz @ 1.8 — 5.5V, 0 — 10 MHz @ 2.7 — 5.5V
–ATtiny2313: 0 — 10 MHz @ 2.7 — 5.5V, 0 — 20 MHz @ 4.5 — 5.5V
 

Обрати внимание, что есть особые низковольтные серии (например 2313V низковльтная) у которых нижня граница напряжения питания сильно меньше. Также стоит обратить внимание на следующий пункт, про частоты. Тут показана зависимость максимальной частоты от напряжения питания. Видно, что на низком напряжении предельные частоты ниже. А низковольтные серии раза в два медленней своих высоковольтных коллег. Впрочем, разгону все процессоры покорны ;))))) (далее…)

Read More »

Основы на пальцах. Часть 4

Но диоды, резисторы, транзисторы и конденсаторы это так, лишь обвязка. Особо на них не развернешься (нет, маньяки, конечно могут, но габариты устройств там будут феерические). Самое вкусное нас поджидает в микросхемах :)
Делятся они на цифровые и аналоговые. Для начала кратко пробегусь по цифровым микросхемам.

Миром правит цифра!

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

Основы цифровой схемотехники
Во избежания путаницы смыслов, в терминологии ключей и транзисторов принято следующее соглашение. Ключ считается открытым или закрытым для протекания тока, как кран на трубе. С точки зрения же механического исполнения он может быть замкнут или разомкнут. Так что открыт = замкнут, закрыт = разомкнут. И не следует путать с англоязычной нотацией, где Open = открыт если речь идет о транзисторе или электронном ключе и Open = разомкнут если речь идет о механическом рубильнике. Там Open-Close следует рассматривать в общем контексте текущего случая. Велик и могуч русский язык! =)

Выход в микросхеме бывает разных типов. Различают push-pull и open drain (в нашей литературе его называют Открытым Коллектором или ОК). Отличие заключается в способе выдачи сигнала на выход. В Push-Pull выходе когда нужен низкий уровень, то выход тупо и беспрекословно замыкается на землю, имеющую нулевой потенциал, а когда высокий, то на напряжение питания.
В открытом коллекторе все несколько иначе. Когда нам надо получить низкий уровень, то мы сажаем ногу на землю, а вот высокий уровень получается подтягивающим резистором (pullup), который, в отсутствии посадки на землю и большого сопротивления висящей на выходе нагрузке, заводит на ногу высокий потенциал. Тут можешь вспомнить закон Ома и посчитать какое будет напряжение выхода на открытом коллекторе если подтягивающий резистор обычно порядка 1КилоОм, а сопротивление входа больше 1МегаОм. Тип выхода определяется из документации на микросхему, некоторые микрухи имеют программируемый выход, например, все контроллеры AVR. Исходя из этого становится понятен смысл регистров Port и DDR в контроллере AVR – они определяют тип выхода Open Drain+PullUp, Push-Pull или просто Open Drain.

(далее…)

Read More »

AVR. Учебный курс. Устройство и работа портов ввода-вывода

С внешним миром микроконтроллер общается через порты ввода вывода. Схема порта ввода вывода указана в даташите:

Но новичку там разобраться довольно сложно. Поэтому я ее несколько упростил (далее…)

Read More »

AVR. Учебный Курс. Управляемый вектор прерывания

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

Простой пример — таймер и его прерывание по переполнению.
Мы можем задавать выдержку и по прерыванию делать какие-нибудь операции. Но если в один момент времени мы хотим чтобы таймер по прерванию сделал одну операцию, а потом другую, третью. Да сколько угодно, в зависимости от состояния. А вектор один.

Или, например, USART. Нам запросто может потребоваться, чтобы в зависимости от режима на прерывание по приходу байта выполнялся разный код. В одном режиме — выдача приветствия, в другом посыл матом в баню. В третьем удар в голову. А вектор один.

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

То есть в свитче вида:

1
2
3
4
5
6
7
switch(x)
	{
	1: Действие 1
	2: Действие 2
	3: Действие 3
	4: Действие 4
	}

Будет последовательное сравнение х вначале с 1, потом с 2, потом с 3 и так до перебора всех вариантов. А в таком случае реакция на Действие 1 будет быстрей чем реакция на Действие 4. Особо важно это при расчете точных временных интервалов на таймере.

Но есть простое решение этой проблемы — индексный переход. Достаточно перед тем как мы начнем ожидать прерывание предварительно загрузить в переменные (а можно и сразу в индексный регистр Z) направление куда нам надо перенаправить наш вектор и воткнуть в обработчик прерывания индексный переход. И вуаля! Переход будет туда куда нужно, без всякого сравнения вариантов.
(далее…)

Read More »

AVR. Учебный Курс. Оценка загрузки контроллера.

Как оценить загруженность микроконтроллера? С памятью все понятно — размеры занимаемого кода и оперативной памяти показывает компилятор, а что делать с процессорным временем? Конечно, в линейной программе можно взять и посчитать время выполнения каждой процедуры и станет ясно успеет микроконтроллер выполнить все на него повешанное или слажает в каком-нибудь критичном месте.
Куда сложней оценивать время в кооперативной операционной системе реального времени. Тут задачка получается нетривиальной — у нас куча процессов скачут через диспетчер. В ходе программирования задачи навешиваешь одну за другой, как бусинки на нить — каждый процесс обработки чего либо составляет подобную цепочку, а всего их может быть просто тьма. Ядро же у контроллера всего одно, а значит выполнять можно всего одну задачу за раз и если у нас в диспетчере скопится много критичных ко времени процессов (вообще их лучше развешивать на прерывания, но бывает и прерываний на всех не напасешься), то возможно либо переполнение очереди диспетчера, либо превышение времени ожидания, что тоже не праздник.
Самое западло в том, что умозрительно отлаживать такие вещи довольно сложно. Единственный вариант — рисовать временные диаграммы запуска каждой задачи и смотреть где у нас узкие места. Еще можно попробовать в AVR Studio поставить Break Point на переполнение диспетчера, но студия не сэмулирует всю ту прорву периферии, а в пошаговой отладке этого не увидеть — да и момент надо подобрать так, чтобы все навалилось.

В один момент мне пришла в голову одна идея — а почему бы не заставить рисовать временные диаграммы работы задач сам контроллер? Это же просто! Берем и в диспетчере, перед вызовом задачи выставляем бит порта в 1. А когда диспетчер задач опустошается полностью, то есть выполняется переход на Idle — сбрасываем бит в 0. В результате, у нас на выходе будет подобие ШИМ. Если постоянно крутится Idle — будут нули перманентно. Если же проц в поте лица гонит через себя непрерывно код, то будут высокий уровнь сплошняком. А если все прерывисто — что то ШИМообразное. Причем чем больше загрузка процессора тем выше заполнение. Можно поставить интегрирующую RC цепочку и получим аналоговый сигнал. Хоть на стрелочный индикатор заводи :). Сказано — сделано.
(далее…)

Read More »

AVR. Учебный курс. Операционная система. Пример.

Отлично, с теорией работы ОС ознакомил. Устанавливать научил, осталось научить использовать весь этот конвеерно таймерный шухер. Чем я сейчас и займусь. Сразу берем быка за рога и формулируем учебно-боевую программу.
Тестовое задание:
Пусть у нас будет ATMega8, с несколькими кнопками. АЦП и подключеним к компу через UART. На меге будет три светодиода.

  • Девайс должен при включении начинать мигать зеленым диодом, мол работаю.
  • При этом раз в секунду сканировать показания АЦП и если показания ниже порога — Моргать красным диодом.
  • По сигналу с UARТ с целью защиты от ошибок сделать по байту ‘R’ установку флага готовности, а потом, в течении 10ms если не придет байт ‘A’ сбросить флаг готовности и игнорировать все входящие байты кроме ‘R’. Если ‘A’ придет в течении 10мс после ‘R’, то отправить в UART ответ и зажечь белый диод на 1 секунду.

Вот так вот, не сильно сложно. Но мне просто лень делать что либо сложней, а для тестовой задачи сгодится. (далее…)

Read More »

AVR. Учебный курс. Операционная система. Установка

Ядро у нас есть, теперь осталось это все хозяйство запихать на МК. Для этого всего лишь надо рассовать нужные части кода в исходник. Показывать буду на примере ATmega8. Для других МК разница минимальная. Может быть с таймером что нибудь помудрить придется, но не более того.
Например, недавно, вкорячивал ту же схему на ATmega168, так пришлось подправить иницилизацию таймера — регистры там зовутся по другому. Пришлось изменить макрос OUTI — так как многие привычные уже регистры перестали загружаться через комадну OUT — выпали из диапазона, только через LDS/STS ну и, собственно, все хлопоты. Потратил минут 20 на переименование регистров и заработало.
(далее…)

Read More »

AVR. Учебный курс. Операционная система. Таймерная служба

Третья часть марлезонского балета описалова самопальной операционной системы для AVR.

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

В чем ее суть ее работы:
Время разбивается на интервалы, скажем, по 1мс. Такой выдержки хватает для большинства задач. Также у нас должна быть очередь программных таймеров, размещенных в ОЗУ. На каждый таймер отводится три байта:
Первый — идентификатор задачи. Два других — выдержка в миллисекундах.

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

Один из свободных аппаратных таймеров программируем на то, чтобы он генерировал прерывание каждые 0.001с

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

По прерыванию мы берем из очереди таймеров первый байт и сравниваем его с 0xFF, за 0xFF принято неактивное состояние. Если же там не 0xFF, то значит это идентификатор задачи, а таймер активен. Поэтому берем третий байт, декрементируем его, если он стал равен нулю декрементируем второй байт и если оба байта не стали равны нулю переходим к проверке следующего байта. В случае если время истекло, то идентификатор задачи пихается в очередь задач на исполнение. (далее…)

Read More »

AVR. Учебный курс. Операционная система. Диспетчер задач.

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

Общая диаграмма работы ОС

Что из себя представляет задача
Это практически то же самое, что и процедура, вызываемая командой RCALL с тремя отличиями:

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

Сама задача представляет собой обычную процедуру, записанную без каких либо замудреностей.
(далее…)

Read More »

AVR. Учебный курс. Операционная система. Введение.

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

В результате было написано микроядро. Камрад Serg2x2 подглядел концепцию в прошивке сотового телефона Motorola и портировал на микроконтроллер АТ89С2051, после ее перенесли на AVR, а я привел все в библиотечный и структурированный вид, обвязал все удобными макросами, а также подробно описал и задокументировал. Так что теперь интеграция ядра операционки в проект под микроконтроллер AVR занимает буквально пару минут работы Copy-Paste.

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

Параметры и системные требования микроядра:

  • Занимаемый обьем в Flash — 500 байт, при желании можно ужать до 400 байт, выкинув ненужные функции.
  • Рекомендуемый объем RAM — не менее 20 байт+стек, впрочем, можно еще ужать если нагрузка небольшая.
  • Крайне желательная поддержка команд STS и LDS, можно и без них, но неудобно. Впрочем, макросы решают.

(далее…)

Read More »

AVR. Учебный курс. Скелет программы

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

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

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

Суперцикл
Все программы на микроконтроллерах обычно зацикленные. Т.е. у нас есть какой то главный цикл, который вращается непрерывно.

Структура же программы при этом следующая:

  • Макросы и макроопредения
  • Сегмент ОЗУ
  • Точка входа — ORG 0000
  • Таблица векторов — и вектора, ведущие в секцию обработчиков прерываний
  • Обработчики прерываний — тела обработчиков, возврат отсюда только по RETI
  • Инициализация памяти — а вот уже отсюда начинается активная часть программы
  • Инициализация стека
  • Инициализация внутренней периферии — программирование и запуск в работу всяких таймеров, интерфейсов, выставление портов ввода-вывода в нужные уровни. Разрешение прерываний.
  • Инициализация внешней периферии — инициализация дисплеев, внешней памяти, разных аппаратных примочек, что подключены к микроконтроллеру извне.
  • Запуск фоновых процессов — процессы работающие непрерывно, вне зависимости от условий. Такие как сканирование клавиатуры, обновление экрана и так далее.
  • Главный цикл — тут уже идет вся управляющая логика программы.
  • Сегмент ЕЕПРОМ

(далее…)

Read More »

AVR. Учебный курс. Стартовая инициализация

Инициализация памяти
Мало кто подозревает о том, что при включении в оперативке далеко не всегда все байты равны 0xFF. Они могут, но не обязаны. Равно как и регистры РОН не всегда равны нулю при запуске. Обычно да, все обнулено, но я несколько раз сталкивался со случаями когда после перезапуска и/или включения-выключения питания, микроконтроллер начинал творить не пойми что. Особнно часто возникает когда питание выключаешь, а потом, спустя некоторое время, пара минут, не больше, включаешь. А всему виной остаточные значения в регистрах.

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

1
2
3
4
5
6
7
8
9
10
11
12
RAM_Flush:	LDI	ZL,Low(SRAM_START)	; Адрес начала ОЗУ в индекс
		LDI	ZH,High(SRAM_START)
		CLR	R16			; Очищаем R16
Flush:		ST 	Z+,R16			; Сохраняем 0 в ячейку памяти
		CPI	ZH,High(RAMEND+1)	; Достигли конца оперативки?
		BRNE	Flush			; Нет? Крутимся дальше!
 
		CPI	ZL,Low(RAMEND+1)	; А младший байт достиг конца?
		BRNE	Flush
 
		CLR	ZL			; Очищаем индекс
		CLR	ZH

Поскольку адрес оперативки у нас двубайтный, то мы вначале смотрим, чтобы старший байт совпал с концом, а потом добиваем оставшиеся 255 байт в младшем байте адреса.
Далее убиваем все регистры от первого до последнего. Все, контроллер готов к работе.

1
2
3
4
5
		LDI	ZL, 30		; Адрес самого старшего регистра	
		CLR	ZH		; А тут у нас будет ноль
		DEC	ZL		; Уменьшая адрес
		ST	Z, ZH		; Записываем в регистр 0
		BRNE	PC-2		; Пока не перебрали все не успокоились

За процедурку зануления регистров спасибо Testicq

Либо значения сразу же инициализируются нужными величинами. Но, обычно, я от нуля всегда пляшу. Поэтому зануляю все.

З.Ы.
Кстати, о оперативке. Нашел я недавно планку оперативной памяти на 1килобайт, древнюю как говно мамонта, еще на ферромагнитных кольцах.

Read More »

AVR. Учебный Курс. Типовые конструкции

При написании программ постоянно приходится использовать разные стандартные конструкции вроде циклов, операторов выбора, перехода, сравнения. Всякие там if-then-else или case-switch. В высокоуровневых языках это все уже готово, а на ассемблере приходится изобретать каждый раз заново.
Впрочем, такие вещи пишутся один раз, а дальше просто по наезженной тропинке применяются везде, где потребуется. Заодно и оптимизируются по ходу процесса.

▌Условие if-then-else
Тут проще всего методом последовательной проверки проложить маршрут до нужного блока кода. Приведу пример:

1
2
3
4
5
6
7
8
9
if (А>=B)
 	{
	action_a
	}
else 
	{
	action_b
	}
next_action

Как это проще всего сделать на ассемблере?
(далее…)

Read More »

AVR. Учебный курс. Ветвления на индексных переходах

Таблицы переходов
Вот представь, что нам надо сделать мега CASE, когда на вход валится число от 1 до 100 и нам надо сто вариантов действий.

Как будешь делать? Если лепить сто штук CPI с последующими переходами, то можно дальше убиться головой об стену. У тебя только эти CPI/BR** сожрут половину памяти кристалла. Учитывая, что каждая CPI это два байта, а каждый BR** еще байт. А о том сколько тактов эта шняга будет выполняться я даже не упоминаю.

Делается это все круче. Помнишь я тебе рассказывал в прошлых уроках о таких командах как ICALL и IJMP. Нет, это не новомодная яблочная истерия, а индексный переход. Прикол в том, что переход (или вызов подпрограммы, не важно) осуществляется тут не по метке, а по адресу в регистре Z (о том что Z это пара R30:R31 я пожалуй больше напоминать не буду, пора бы запомнить).
(далее…)

Read More »