24 сентября 2012 в 07:38

Прошиваем AVR вручную tutorial


Картинка для привлечения внимания — xkcd

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

Радуясь, что еще не забыли курс ассемблера, вы кое-как написали программу палочкой на песке. Среди уцелевших вещей каким-то чудом оказалась распечатка документации на контроллер (хорошо, что вы еще не успели пустить её на растопку!), и программу удалось перевести в машинные коды. Осталась самая ерунда — прошить её в контроллер. Но в радиусе 500 километров нет ни одного программатора, не говоря уже о компьютерах. У вас только источник питания (батарея из картошки кокосов) и пара кусков провода.

Как же прошить МК фактически голыми руками?

В качестве подопытного будет выступать МК ATtiny13 фирмы Atmel. Описанная методика работает практически с любым контроллером семейства AVR, разве что коды команд могут незначительно отличаться.

Интерфейс

Самым распространенным и удобным интерфейсом для прошивки AVR является SPI (Serial Peripheral Interface). Для подключения по SPI нужно всего четыре провода, не считая земли:
  • SCK — тактовый сигнал, синхронизирует все операции обмена данными;
  • MOSI (Master Out Slave In) — линия данных от ведущего устройства к ведомому;
  • MISO (Master In Slave Out) — линия данных, наоборот, от ведомого устройства к ведущему;
  • RESET — для разрешения прошивки по SPI нужно подать логический «0» на этот вывод.

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

Рис. 1. Простейшая схема подключения по SPI.

Для своего же удобства можно добавить индикацию входных сигналов. Схема усложняется, но не чрезмерно:

Рис. 2. Схема с индикацией сигналов.

Защита от дребезга


К сожалению, просто используя кнопки для формированя сигналов SPI, хорошего результата мы не добьёмся. Причина этого — в неприятном явлении, которое называется дребезг контактов. При замыкании механические контакты соударяются, отскакивают друг от друга, и вместо одного импульса получается несколько. Для подавления дребезга придется собрать простую схему из пары логических элементов:

Рис. 3. RS-триггер для подавления дребезга.

Это RS-триггер, который переключается в состояние «1» в момент замыкания нижнего контакта переключателя и игнорирует остальные импульсы дребезга. Сброс триггера обратно в «0» происходит при замыкании верхнего контакта, то есть при отпускании кнопки.

«Ишь, разбежался!» — скажет читатель, — «Я же на необитаемом острове сижу. Где я тут возьму триггеры?» Хорошо, можно избавиться от дребезга и без электронных схем. Нужно только заменить «сухой» контакт на мокрый жидкостный. Выключателем будут служить два электрода, опускаемые в проводящую жидкость.

Сигналы MOSI и RESET не требуют подавления дребезга, в отличие от SCK: здесь значение имеет только уровень сигнала в момент выборки, а не его фронты.

Как работает SPI



Рис. 4. Временная диаграмма работы SPI.

SPI является синхронным интерфейсом: все операции синхронизированы фронтами тактового сигнала (SCK), который вырабатывается ведущим устройством. Максимальная скорость передачи ограничена величиной 1/4 тактовой частоты контроллера. На минимальную же скорость нет никаких ограничений: без тактового сигнала обмен данными «замораживается», и интерфейс может оставаться в статическом состоянии сколь угодно долго.

Передача по SPI осуществляется в полнодуплексном режиме, по одному биту за такт в каждую сторону. По возрастающему фронту сигнала SCK ведомое устройство считывает очередной бит с линии MOSI, а по спадающему — выдает следующий бит на линию MISO. Все внимание на рисунок 4.

Протокол прошивки

Все общение программатора с МК состоит из отправки 32-битных команд и приема ответов контроллера. Полный перечень команд есть в datasheet'е, а здесь перечислим, какие операции необходимо выполнить для прошивки МК:
  1. Перевод контроллера в режим программирования;
  2. (опционально) Чтение идентификатора устройства;
  3. Стирание;
  4. Запись во flash;
  5. (опционально) Проверка записанного;

Рассмотрим каждый шаг подробно.

Включение режима программирования


Режим программирования включается подачей «0» на ногу RESET. Но есть некоторые тонкости. Atmel рекомендует сначала выставить на выводах RESET и SCK низкий уровень, а только потом подавать на контроллер питание. Если такой возможности нет, нужно после включения питания подать «0» на SCK, а затем положительный импульс на RESET:


Рис. 5. Перевод МК в режим программирования.

Но и это еще не все. Далее нужно передать команду на собственно включение режима программирования: 10101100 01010011 xxxxxxxx xxxxxxxx


Рис. 6. Команда «Program Enable».

Биты, обозначенные как x, могут быть любыми. Во время передачи третьего байта контроллер должен переслать обратно второй байт (01010011). Если это произошло, значит, все хорошо, команда принята, контроллер ждет дальнейших инструкций. Если ответ отличается, нужно перезагрузить МК и попробовать все сначала.

Проверка идентификатора




Рис. 7. Команда «Read Signature Byte».

Прежде чем что-либо писать в память МК, нужно убедиться, что перед нами именно та модель, которая нужна. Каждая модель контроллера имеет свой трехбайтный идентификатор (Signature). Прочитать его можно командами вида
00110000 000xxxxx xxxxxxbb xxxxxxxx
Вместо bb (третий байт команды) следует подставить 00 для первого байта идентификатора, 01 — для второго и 10 — для третьего. Соответствующий байт идентификатора будет передан контроллером при отправке 4-го байта команды.

Для ATtiny13 значение идентификатора равно 00011110 10010000 00000111 (0x1E 90 07).

Очистка контроллера




Рис. 8. Команда «Chip Erase».

Следующим шагом будет очистка памяти МК, которая осуществляется посылкой команды «Chip Erase»
10101100 100xxxxx xxxxxxxx xxxxxxxx
Этой командой выполняется стирание содержимого Flash и EEPROM (все ячейки будут содержать FF), а также снятие lock-битов, если они установлены.

Запись во flash-память


Память программ (Flash) в ATtiny13 состоит из 512 двухбайтных слов (1К байт). Адрес слова имеет разрядность 9 бит. Flash-память разделена на страницы, каждая страница имеет размер 16 слов (всего получается 32 страницы). Запись во flash осуществляется в два этапа.

Сначала необходимо загрузить данные в буфер страницы, для этого используется команда «Load Program Memory Page»
01000000 000xxxxx xxxxbbbb iiiiiiii — для загрузки младшего байта слова, и 01001000 000xxxxx xxxxbbbb iiiiiiii — для загрузки старшего.
4 младших бита 3-го байта команды bbbb — адрес слова на странице, iiiiiiii — загружаемый байт. Сначала всегда должен загружаться младший байт слова, а затем — старший байт того же слова.


Рис. 9. Команда «Load Program Memory Page».

После того, как буфер страницы загружен, нужно выполнить команду «Write Program Memory Page» 01001100 0000000a bbbbxxxx xxxxxxxx для записи страницы непосредственно в память контроллера.
Младший бит второго байта и старшие 4 бита третьего a:bbbb — пятибитный номер страницы для записи.


Рис. 10. Команда «Write Program Memory Page».

Все это выглядит довольно запутанно, но ничего сложного нет. Адрес любого байта памяти программ состоит из 10 бит: ppppp:bbbb:w, где
ppppp — номер страницы (используется в команде «Write Program Memory Page»);
bbbb — адрес слова на странице (в команде «Load Program Memory Page»);
w — бит, определяющий старший или младший байт в слове (зашифрован в первом байте команды «Load Program Memory Page»).

Чтение flash




Рис. 11. Команда «Read Program Memory».

После записи прошивки в МК неплохо бы проверить записанное, так как никакой проверки целостности данных не выполнялось. Единственный способ проверки состоит в том, чтобы прочитать весь объем flash-памяти и сравнить с оригиналом.

Читать память программ легче, чем писать в нее. Забудьте про страничную организацию, чтение выполняется побайтно. Команда «Read Program Memory» выглядит так:
00100000 0000000a bbbbbbbb xxxxxxxx — для чтения младшего байта слова, и 00101000 0000000a bbbbbbbb xxxxxxxx — для старшего.
Младший бит второго байта и весь третий байт a:bbbbbbbb — адрес слова в памяти. Прочитанный байт возвращается во время передачи 4-го байта команды.

Завершение программирования


Пожалуй, самая простая операция. Чтобы завершить программирование и перевести МК в рабочий режим, достаточно подать на RESET логический уровень «1». Контроллер запустится и будет работать по новой программе.

Практика

Настало время воспользоваться полученными знаниями на практике. Жертва эксперимента — ATtiny13 — воткнут в макетную плату, рядом собран формирователь сигналов, всё готово:

Рис. 12. Экспериментальная схема.

Шить будем программу вида «проще некуда»:
ldi R24,  0x02
out DDRB, R24
out PORTB,R24	
L1: rjmp  L1

Всё, что она делает — это выдает единицу на ногу PB1 и уходит в бесконечный цикл. В машинных кодах она занимает всего четыре слова:
E082 BB87 BB88 CFFF

Для прошивки её в контроллер необходимо набрать следующие команды:
1010 1100  0101 0011  0000 0000  0000 0000 // program enable

1010 1100  1000 0000  0000 0000  0000 0000 // chip erase

0100 0000  0000 0000  0000 0000  1000 0010 // load addr.0000  low byte 82
0100 1000  0000 0000  0000 0000  1110 0000 // load addr.0000 high byte E0

0100 0000  0000 0000  0000 0001  1000 0111 // load addr.0001  low byte 87
0100 1000  0000 0000  0000 0001  1011 1011 // load addr.0001 high byte BB

0100 0000  0000 0000  0000 0010  1000 1000 // load addr.0010  low byte 88
0100 1000  0000 0000  0000 0010  1011 1011 // load addr.0010 high byte BB

0100 0000  0000 0000  0000 0011  1111 1111 // load addr.0011  low byte FF
0100 1000  0000 0000  0000 0011  1100 1111 // load addr.0011 high byte CF

0100 1100  0000 0000  0000 0000  0000 0000 // write page

Ключ на старт, поехали!


Всего 425 нажатий, и МК оживает. Теперь вас точно найдут и спасут с этого проклятого острова.
+169
74097
385
Ocelot 188,3

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

+16
Pinsky, #
Думаю хаб ненормальное программирование был бы тут к месту!
+1
Ocelot, #
Добавил.
+3
Lamaster, #
Вот это я понимаю — настоящий программист!
+2
mark_ablov, #
Занятно, тоже делал такое, но для PIC'ов микрочиповских.
+7
dmitriev_dmitry, #
Хотел подколоть автора запросив видео, но когда увидел, что оно есть очень сильно его (автора) заувожал. Сюжет для неплохого техно-кино (добавить сцену падения самолета и спасения программиста)
+2
spq, #
увожил-увожил, конечно
+1
smwed, #
Ага, новый сериал снимут с авиакрушением на острове: «Lost Programmer»… :)
+2
subvillion, #
Я одному студенту задачу дал, прошить много PIC по аналогичной системе, в качестве наказания за прогул лекций. Принес через 2 дня, все полностью и правильно рабочие! Этот засранец их через Arduino «шил»!
+10
Ocelot, #
Прошивка состояла из повторяющихся строк «я больше не буду забивать лекции»?
+1
subvillion, #
)) Все должны быть разные, тк это заготовки для лаб.
+5
wowscheg, #
Вспомнились журналы радио, где простынями на несколько страниц был напечатан код из единиц и нулей. Вооружившись линейкой и карандашиком вбивали прошивку в ручную. Вероятность ошибки ввода была весьма высока, но самое страшное если была опечатка в самом журнале.
+2
Ocelot, #
Все-таки тогда были в ходу программаторы: клавиатура + пара регистров (иногда еще индикатор) позволяли вбивать прошивку сразу в хексах, что было гораздо быстрее и проще, чем по одному биту.
+1
klirichek, #
Так-то оно да, быстрее.
Но и набивать нужно было, как правило, существенно больше пары-тройки машинных слов…

Помню, из книжки с хексов набирал CP/M.
На несчастных 8 килобайт ушло несколько недель.
+1
ploop, #
Приходилось набивать программы для спектрума с подшивок ZX-ревю.
Но там было проще: в каждой строке (или блоке, забыл уже) проверялась контрольная сумма, и найти ошибки было элементарно. Но убогие ксерокопии иногда просто не позволяли прочитать символ, приходилось методом тыка перебирать…
НЛО прилетело и опубликовало эту надпись здесь
+2
WVitek, #
А там не шестнадцатериные ли коды были?
Самому довелось так 8Кб интерпретатора BASIC набирать. И там поблочные контрольные суммы имелись.
+2
Bublik, #
HEX там был :-)
0
mihmig, #
Не, там колонка с контрольной суммой вроде была…
0
Dan_Vaganov, #
Отдельный топик — программирование азбукой морзе
+9
Kidar, #
В молодости прошивал 573РФ2 при помощи кучи выключателей с адресом, переключателей с данными и кнопкой «Запись»
Интересное было занятие на внимательность!

При ошибке привязывал ПЗУ на метровую палочку и шел к знакомому сварщику. Подержишь несколько минут окошко к месту сварки — проверишь. Если все стерлось, значит можно по новой программировать.
Вот такие технологии были на необитаемом острове под названием СССР.
0
DIHALT, #
Да ладно, все так шили. Не только у нас, но и у них.
0
Kidar, #
Насчет так шили, то да, у всех так было.

Интересно было стирать ульрафиолетом от электросварки, сам это придумал.
Главное в этом процессе поймать баланс, чтобы информация стерлась и кристалл не получил большого облучения, иначе ресурс по количеству записей резко уменьшится, а их и так было немного совсем.
Получалось как при радиации — не нахватать лишней дозы.
Лампу ультрафиолетовую тогда так и не приобрел, а разбивать ДРЛ тоже не стал.
Так и прошел этот период рядом со сварщиком.
0
DIHALT, #
А я к медикам на кварцевание кабинетов носил. Сварщиков по близости не было, а медики знакомые были.
0
Kidar, #
К медикам, это хорошо!
У них кроме кварцевой лампы были иглы от шприца — для рисования плат,
таблетки аспирина — для очистки изоляции эмалированных проводов,
спирт — очистка плат и приготовления спирто-канифольного флюса.
Наверняка еще что-то можно вспомнить.
0
Ocelot, #
Скальпель же! Универсальный инструмент по сути. И зажимы хирургические — для монтажа удобнее пинцетов во много раз.
0
Kidar, #
Точно, про скальпель забыл, очень многие радиолюбители его использовали.
У меня вместо него применялось заточенное ножовочное полотно.
Пинцет еще был очень удобный, почему-то он назывался медицинским. Наверное и был оттуда.
А вот зажимом хирургическим не удалось попользоваться, но в других руках видел, хозяин сего приспособления был доволен.
Груша медицинская до сих пор в ходу — ей удобно выдувать пыль из всех щелей и высасывать воду с ковриков в машине.
Зубными бормашинками сверлили платы.
0
m0Ray, #
Мой батя, от которого я перенял большинство радиолюбительских навыков, как-то купил в «медтехнике» наконечник от бормашины и набор зубных фрез, присобачил к ним купленный на барахолке моторчик. Навернул на хвостовики мелких свёрл проволоку определённого диаметра, чтоб вставлялись в бормашину. Получилась неплохая микродрель с кучей полезных насадок. Потом он ещё изготовил небольшие круги для шлифовки и резки — вот была вундервафля!
0
mark_ablov, #
Жаль сейчас на одноразовые перешли.
Старый добрый массивный многоразовый труднее найти стало.
0
Kidar, #
У меня осталось несколько штук.
Стекло выбиваешь, волоски-паутинки от кристалла удаляешь, чтобы каждая ножка «висела», а затем к ножкам короткими проволочками припаиваешь современный контроллер в исполнении SO.
Получается наездник «новый на старом».
Решение использую для написания программ на этапе отладки, так как программатор ChipProg, а переходники отсутствуют.
Старые РФ-ки можно использовать для изготовления переходника к программатору для внутрисхемного программирования.
НЛО прилетело и опубликовало эту надпись здесь
0
Kidar, #
Понравилась фраза «толпа РФ», вначале прочитал как Российская Федерация.

Да я знаю про технологии, которые были в СССР, очень отличные технологии! Участвовал в программе «Буран», так что повидал многое.
Но с одной стороны был Буран, а с другой пришлось делать прибор, который проверял логические микросхемы при покупке на рынке! Был большой процент брака и обидно, когда потратишь целый день на покупку микросхемы, а дома убеждаешься, что она неисправна. Поэтому проверял, не отходя от кассы.
Видимо их таскали с завода до контроля ОТК, или брали из кучи бракованных.
Лампу тоже можно было сделать, но массово не работали. Синклеры, АОНы да звоночки музыкальные для себя делали.
НЛО прилетело и опубликовало эту надпись здесь
0
Kidar, #
Рынок был основным поставщиком деталей, больше брать было негде, если не считать радиосвалки, разобранные телевизоры и дядю, продающего детали из-под полы, как в фильме «Иван Васильевич меняет профессию».
Одним словом — необитаемый остров, как в теме автора.
Да и рынки гоняли с места на место, прекрасно помню этапы его становления в Москве: Детский мир, магазин Пионер, ..., и далее, вплоть до Митинского. Как толпы радиолюбителей ездили в метро до Белорусской, чтобы прокатившись полчаса на электричке, добраться до очередного временно разрешенного места.

Мне показалось, что основная мысль рассказа была не только показать основы программирования, а также то, что инженер должен использовать любую возможность и способ, чтобы найти выход из сложившейся ситуации.
НЛО прилетело и опубликовало эту надпись здесь
+1
Kidar, #
Конечно, ситуация описанная в рассказе в жизни не произойдет, но я считаю, что автор нашел красивый способ для подачи основ программирования.
Программно-фантастический рассказ, который вызвал большой отклик у жителей острова Хабра.
+13
sl4mmer, #
Благодаря таким топикам, хабр все еще торт.
+4
sourcerer, #
Добавление устройства для чтения перфолент могло бы упростить задачу ввода большого объема данных в контроллер. Нужно лишь фотодиод найти, а ленту и вручную протягивать можно.
+1
foff4ik, #
А зачем фотодиод, можно и железный контакт сунуть же, ну и вроде раньше слышал как то спиливали транзисторы дабы этот светодиод получить.
0
RaJa, #
Да обычный транзистор в металлическом корпусе верхнюю крышку спиливаешь и все. Сам по себе P-N переход светочувствительный.
0
sourcerer, #
Не на всяком необитаемом острове есть транзисторы, как и фотодиоды. А вот железный контакт — это может прокатить.
0
RaJa, #
Конечно, я не про необитаемый остров, а на конкретный вопрос про фотоприемник ответил.
+1
imwode, #
А вот как написать программу: danamlund.dk/pic_microcontroller_blinking_led_without_cheating.html

кстати, у SR-дебаунсера есть одна неприятная особенность — он не может с тактовыми кнопками работать :-)
+1
Ocelot, #
C тактовыми кнопками вместо RS-триггера можно использовать одновибратор:
Вот так
0
Nepherhotep, #
На счет дребезга — более простое, хотя и менее качественное решение, — подключить параллельно кнопке емкость. Как правило для МК этого бывает достаточно.
+1
imwode, #
низзя так делать
там через контакты кнопки бешеные токи текут
и всплески напряжения превышающие максимум рейтинги

блин, а я тут все выходные дебаунсил геркон. в итоге сделал программную маску на 400-500мс, потому что хардовый дебаунс прекрасно выглядел на экране осцилла, но все равно было многократное срабатывание. Я так и не понял почему. Дело осложнялось тем, что геркон стоит в счетчике горячей воды. Т.е. чтобы нормально потестить, надо во-первых ждать, а во-вторых сливать в канализацию недешевую горячую воду. Плюнул.
0
Nepherhotep, #
И что страшного может произойти из-за емкости?
+3
Nepherhotep, #
Спасибо за ссылку.
Тем не менее, хотя я и не агитирую именно за аппаратный дебаунс, но он имеет право на существование. Для чувствительных контактов (случай описанный в статье) вводят резистор.
Собственно, описание в контр-статье :)
www.labbookpages.co.uk/electronics/debounce.html
+2
imwode, #
Вот там не зря стоит буффер после всей этой лабуды. Потому что 100кОм пуллап + серийный резистор создают неплохой такой делитель напряжения вместе с входным напряжением МК. В итоге при разомкнутом контакте на входе МК без буффера имеем вместо VDD какой-нить VDD/2.

Я не то что думаю что он «имеет право на существование», я думаю, что в немаленьком количестве проектов это вообще маст.
+5
imwode, #
«Сам по себе процесс сборки был весьма поучитель-
ным, он содержал в себе курс по цифровой логике, ис-
кусству пайки, а также дух новизны. Проблема была в
том, что даже если вам удавалось собрать компьютер,
то все что вы имели в результате представяло собой
коробку с мигающими светодиодами и с 256 байтами
памяти. Программа в нем размещалась только после
того, как вы вводили восьмиричные числа при помо-
щи крохотных тумблеров, которыми легко можно было
сломать ногти, а в случае проблемы, о ней можно бы-
ло узнать только по перемигиванию светодиодов, ко-
торые также выводили информацию в восьмиричном
виде. Но, какая, к черту, разница, как это приходилось
делать? Это было начало начал, и это был компьютер.»
С.Леви. «Хакеры — герои компьютерной революции»
–1
aronsky, #
Круто! Ещё можно пищалки добавить при нажатии на клавиши, получится музыка.
Так можно почти любой синхронный протокол реализовать — I2C будет чуть веселее.
+2
MedVedar, #
Благодаря таким топикам несмотря на все еще веришь в наше будущее. Автору спасибо.
+2
Quadler, #
+5
Ocelot, #
Собственно, эта картинка и стала источником идеи к написанию статьи.
+3
djmorgan, #
Вот клава ля этого)
+2
smwed, #
Эххх. Вот такие люди как автор могут из умывальника, мотка проволоки и магнита собрать какую-нть фазер-мазер-пушку… Завидую :)
+1
xskrip, #
Тему надо назвать «SPI с ручным приводом».
+2
Ocelot, #
Хорошо не с педальным :)
0
allswell, #
классно:) пожалуй, добавлю в избранное)
+1
bagyr, #
Legend has it that Seymore Cray, inventor of the Cray I supercomputer and most of Control Data's computers, actually toggled the first operating system for the CDC7600 in on the front panel from memory when it was first powered on. Seymore, needless to say, is a Real Programmer.

© Real Programmers Don't Use Pascal
+3
iklementiev, #
Найти бы еще способ, чтобы на необитаемом острове в описанной ситуации, прочитать этот топик из закладок.
0
SlavikMIPT, #
главное — правильно преподнести — перевод странички SPI Serial Programming из даташита) Молодец — разобрался, можешь теперь свой программатор сделать
+1
artyums, #
Программирование побитово? Ух ты, я серьезно с детства, как только узнал о битах/байтах, мечтал увидеть, в чем это действительно заключается при программировании. Не пришлось как-то до сих пор.
Огромное спасибо за статью!
0
0xBA0BAB, #
Спасибо! Очень наглядно. Если кто не понимал, как устроен SPI — то сейчас вопросов не осталось бы никаких.

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