Как стать автором
Обновить

Простой программатор для атмеловских 8051

Время на прочтение7 мин
Количество просмотров3K

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

Собственно программатор — голый Arduino с прошивкой, разбирающей HEX-файл построчно и реализующий программирование целевого чипа по SPI. Прошивка и инструкции сложены в репозитории на гитхабе: At89s-prog.

Конкретные чипы (At89s...) здесь скорее для примера. Мы не будем воспевать достоинства 8051-й архитектуры (конечно, они архаичны но у них есть плюсы, благодаря которым они до сих пор сохраняют популярность). У меня в какой‑то момент оказалась их горстка а программатора под рукой не нашлось. Они (те что с индексом S) программируются через SPI, а не стандартным «многоногим» интерфейсом что делает удобным их применение в любительских поделках.

Предисловие

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

Упрощённый подход к прошивке чипов
Упрощённый подход к прошивке чипов

В любительской практике бывает и так, что в одной поделке использовал AVR, в другой ST32, в третьей MSP430, в четвёртой ещё что‑нибудь. Зоопарк чипов в хобби‑проектах имеет свойство копиться со временем. Закупаться соответствующим количеством нужных программаторов не всегда имеет смысл. Дело даже не в деньгах а в том что (как многие «электронщики» знают — со временем становится затруднительно вспомнить где что лежит).

Сам я поэтому часто использую чипы у которых есть встроенный UART‑загрузчик (например ST32 и MSP430 упомянутые). Но в частности Atmel издавна упорно шёл другим путём и многие их контроллеры программируются по SPI. Большинство из них поддержаны в AvrDude и программаторе AVRISP — эта прошивка доступна в примерах Arduino IDE.

Однако с попавшими мне в руки 8051-ми клонами (изначально At89s4051 — удобными 20-ногими узкими чипами — а после и At89s52 — они в стандартных 40-ногих корпусах) — эти инструменты не работают. При этом чипы удобные и стоят (на «али») очень недорого.

Открыв datasheet и почитав раздел про SPI команды я подумал что могу быстренько состряпать самодельный программатор.

При этом удобным показалось чтобы к нему ещё не требовалась дополнительная утилита на стороне компьютера. Отправил файл в последовательный порт — и ура!

Вещь получилась рабочая — одна из первых поделок которые я с её помощью разрабатывал — этот радиоприёмник на Si4735:

ну, вот такой коротковолновый радиоприёмник в наше время :)
ну, вот такой коротковолновый радиоприёмник в наше время :)

Атмеловские 8051-е клоны

Мы рассматриваем такие модификации серии At89... (этот префикс у них означает 8051-е чипы):

  • At89s52 и At89s51 (различаются как 8052 и 8051 — 8 против 4 кб флеш‑памяти, лишний таймер) — в «полных» 40-ногих корпусах, или например в архаичных но милых PLCC

  • At89s4051 и At89s2051 — аналоги 8051 но в уменьшенных 20-ногих корпусах, выведены только P1 и P3.

Обратите внимание на букву S после At89 — она означает модели с программированием по SPI (параллельное тоже доступно впрочем но нас не интересует).

Вообще сейчас есть и более интересные 8051-совместимые контроллеры — наверняка многие замечали китайские STC... — в частности STC8G1K08 — тут и прошивка по UART и встроенный RC‑генератор тактовой частоты, и АЦП. И корпуса похожие. Но документация может оставить чувство лёгкого раздражения с непривычки. В любом случае они за пределами нашей сегодняшней темы.

Применение

Возьмите прошивку (arduino-проект) из репозитория указанного выше.

Прошейте её в какой-нибудь Arduino-модуль, который найдётся под рукой. Там нет какой-то специфики и скорее всего подойдёт любой.

Для примера тут же представлены файл blink.asm и скомпилированный из него файл blink.hex — хотя вы можете написать и скомпилировать собственный код. Например код для цифрового радио на Si4735, упомянутый выше — там уже прошивка объёмистая.

Подключите ваш программатор (прошитый) ардуино к программируемому чипу:

  • подключите питание (GND, VCC и если есть отдельный — то VPP)

  • RST к 9й ноге, SCK, MISO, MOSI к 12, 11, 10 соответственно

  • также нужен кварц на XTAL или внешний генератор тактовой частоты

Например вот подключение «голого» At89s52. Для демонстрации добавлены 2 светодиода которыми прошивка blink.hex будет перемигивать:

слева старый ардуино, справа At89s52 в классическом 40-ногом корпусе
слева старый ардуино, справа At89s52 в классическом 40-ногом корпусе

То же самое с 20-ногим узким At89s4051:

У этих VPP не выведен отдельно - поэтому одним проводом меньше
У этих VPP не выведен отдельно - поэтому одним проводом меньше

Теперь нужно лишь настроить последовательный порт (с которым всё ещё соединён Arduino) на параметры 1200 бод, 1 стоп‑бит, без чётности.

Низкая скорость выбрана чтобы процесс прошивки «успевал» за подачей данных. С некоторыми оговорками её можно увеличить (см. ниже) но м.б. не очень актуально.

Удобно использовать какую‑нибудь терминальную программулину, которая позволит и файл отправить — и следить что программатор отвечает. Однако можно использовать и стандартные инструменты ОС — в частности примеры приведены в виде shell‑файлов под линукс:

stty -F /dev/ttyUSB0 1200 -cstopb -parenb cs8 -icrnl -echo

Настроили последовательный порт. Кроме вышеупомянутых настроек тут ещё параметры для подавления эха и формата переводов строк.

cat /dev/ttyUSB0 &

в бэкграунде читаем (и дампаем) что пишет программатор обратно по ходу работы

cat blink.hex >/dev/ttyUSB0

отправляем файл с прошивкой в последовательный канал.

В случае успеха программатор пишет некую информацию по ходу обработки получаемого файла, выглядит это так:

прошивка, тут всего 30 байт - две строки hex-файла
прошивка, тут всего 30 байт - две строки hex-файла

PRG EN — это ответ на команду перехода в режим программирования (не все чипы содержательно на неё отвечают). SIG — сигнатура чипа. Если она совпадает с даташитом, по крайней мере понятно что интерфейс SPI работает.

Дальше строчки с W@ расшифровываются как «write at <addr> <count>» — вот мы записываем 16 байт по адресу 0x0 (первая строка hex-файла) потом ещё 14 по адресу 0×10 (вторая строка).

В третьей строке программатор обнаруживает признак завершения и пишет `Prg mode off`. Напоследок он дёргает ещё раз ресет — где‑то была такая рекомендация, хотя по-моему и без этого чип нормально запустится в рабочий режим.

Из скрипта burn.sh после выполнения выходим по Ctrl‑C — иначе он висит продолжая ожидать ещё чего-нибудь от программатора :)

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

echo "!" >/dev/ttyUSB0

очистка чипа
очистка чипа

Иногда полезно считать программу обратно из чипа - чтобы верифицировать нет ли ошибки записи, например. Для этого пока реализованаочень простая «фича» — используются такие же команды как для записи строк HEX‑файла, но с вопросительным знаком вместо двоеточия в начале. Поэтому из строки на самом деле берется только адрес и длина считываемых данных, например (в readmem.sh):

echo "?10000000" >/dev/ttyUSB0

Считаем 0x10 байт с нулевого адреса:

считываем 16 байт из памяти программ - совпадают с hex-файлом
считываем 16 байт из памяти программ — совпадают с hex-файлом

Замечания по коду прошивки программатора

Программатор сам возвращается в «ждущий» режим. То есть вы можете отправить ему команду на стирание, потом закачать новый hex‑файл, потом считать память для проверки — между этими действиями не требуется каких‑то дополнительных манипуляций.

Запись в чип происходит после считывания очередной строки hex‑файла — и ведётся она в побайтовом режиме. Постраничный я сначала использовал, но преимуществ у него не нашёл а размер страниц у чипов разный, да ещё и файлы собранные сложными компиляторами (вроде Keil или SDCC) будут содержать строки в сложном порядке и код собирающий данные для страницы выглядит достаточно мутно.

В строке берутся первые четыре байта (9 символов) чтобы определить режим (чтение‑запись), адрес, количество байт — и тип операции (01 — останов). После чего следующие байты непосредственно записываются.

При этом скорость приёма байт по UART должна быть согласована со скоростью операций записи (сейчас сделано с запасом) — да ещё и со скоростью вывода информации обратно пользователю. В частности из‑за этого некоторые отладочные строчки были сокращены — замените W@ на «writing data at» и что‑нибудь в этом духе — и на достаточно объёмных прошивках вы можете получить пропущенные байты при записи:)

Вероятно эту ситуацию можно улучшить с использованием механизма Xon / Xoff, но у меня с первой попытки не получилось — поэтому пока отложил как некритичный импрувмент.

Заключение

Как сказано выше, цель статьи больше в том чтобы обратить внимание на возможность убрать одно из «звеньев» в инструментах для прошивки. С чипами имеющими встроенный загрузчик можно бы убрать и «программатор». Только к сожалению дефолтных загрузчиков использующих hex‑файлы я пока не встречал. А без этого выходит что всё равно сначала нужен программатор чтобы кастомный загрузчик прошить.

Теги:
Хабы:
+6
Комментарии13

Публикации

Ближайшие события