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

в 5:04, , рубрики: 8051, arduino, atmel, микроконтроллеры

В этой заметке речь больше про принцип - программатор можно сделать так, чтобы на стороне компьютера не требовался дополнительный софт. Будем прямо лить 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 по адресу 0x10 (вторая строка).

В третьей строке программатор обнаруживает признак завершения и пишет `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-файлы я пока не встречал. А без этого выходит что всё равно сначала нужен программатор чтобы кастомный загрузчик прошить.

Автор: RodionGork

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js