Всё началось с приобретения автором на вторичном рынке интересного устройства — Smart Response XE (
Поддержка этих устройств прекращена несколько лет назад, и то, что школы закупали по 100-200 долларов за штуку, теперь всплывает на eBay по 10 и меньше. «Железо» там ну очень подходит для гиковских опытов:
- клавиатура на 60 клавиш
- дисплей с разрешением в 384×136, 2 бита на пиксель — аналогично БК, CGA, но 4 не цвета, а градации яркости
- микроконтроллер ATmega128RFA1 (128 кБ флеш-памяти, 4 кБ ПЗУ, 16 кБ ОЗУ, приёмопередатчик стандарта 802.15.4)
- внешняя (по отношению к микроконтроллеру, а не всему устройству) флеш-память на 1 мегабит (128 килобайт) с интерфейсом SPI
- отсек для 4 элементов ААА.
По названию микроконтроллера понятно, что он относится к семейству AVR, а значит, сделать устройство Arduino-совместимым — задача более чем тривиальная…
Из новости на
Но автора больше интересует возможность не поиграть на устройстве, а изучить:
- флеш-память с последовательным интерфейсом SPI
- загрузчики для AVR
- стандарт 802.15.4
Автор начал с написания
Этого достаточно чтобы залить загрузчик Arduino, но не скетч — последовательный порт туда не выведен, без вскрытия корпуса всё равно не обойтись. Также линии TX0 и RX0 первого последовательного порта совмещены с линиями опроса матрицы клавиатуры, а именно — теми, по которым идёт опрос функциональных клавиш по сторонам от дисплея. Но что поделать — автор соорудил вот что:
Туда он вывел линии JTAG, и теперь батарейный отсек открывать не обязательно. А чтобы можно было заливать и скетчи, вывел на этот же разъём и оба последовательных порта, добавив также выключатель, потому что при установленных батарейках устройство по-другому физически выключить невозможно.
Потребовалось довольно долго поработать паяльником, канцелярским ножом и клеевым пистолетом. В общем, «по воздуху» заливать скетчи значительно удобнее, надо для этого срочно что-то изобретать.
Arduino IDE для заливки скетчей использует программу
Перепробовав разные способы преодоления этой проблемы, автор придумал следующее. У устройства есть 128-килобайтная флеш-память с интерфейсом SPI — принимаем данные по проводам (помним, что один девайсы с разъёмом на боку у автора уже есть), используем эту память как буфер, и по радиоканалу отправляем данные в другое устройство. Такой привет от Cybiko.
После написания кода для работы с радиоканалом, а также шрифта, загрузчик стал длиннее 4 килобайт. Поэтому значение HFUSE пришлось поменять с 0xDA to 0xD8. Теперь загрузчик может быть длиной до 8 килобайт, а начальный адрес стал равен 0x1E000. Это отражено в Makefile, но должно быть учтено и при заливке
Приёмопередатчик стандарта 802.15.4 в ATmega128RFA1 изначально предназначен для работы по протоколу
Оказалось, что наименее подвержены помехам от WiFi каналы 15 и 26. Второй из них автор и выбрал. Дисклеймер: переводчик не знает, разрешено ли так упрощать ZigBee. Может быть, стоит ещё немного попрограммировать и реализовать его полностью?
На первом из устройств надо реализовать конечный автомат, передающий данные по протоколу STK500. В большинстве своём передаваемые и принимаемые сообщения самодостаточны, но некоторые привязаны к прошедшим по каналу ранее. Описание диалога приведено
Важной составляющей этого диалога является передача пакетов, предназначенных для записи во флеш-память устройства назначения. У простых микроконтроллеров семейства AVR размер страницы составляет 128 байт, но у ATmega128RFA1 — 256. А у той флеш-памяти, которая подключается по протоколу SPI, он такой же. Программа в первом устройстве при заливке скетча не передаёт его сразу во второе, а пишет его в эту память. Когда же Arduino IDE проверяет правильность записи, ему отправляют то, что туда записалось. Теперь надо передать полученные данные по радиоканалу во второе устройство. При этом переключение с приёма на передачу и обратно происходит довольно часто. Протокол STK500 безразличен к задержкам, но не терпит потери данных (странно, а выше сказано, что задержки на передаче данных тоже сказываются). А потери при беспроводной передаче неизбежны. В ATmega128RFA1 встроена аппаратная реализация повторных запросов при сомнениях в правильности передачи, но автор решил реализовать то же самое программно самостоятельно. Он разработал протокол, при котором в одну сторону проходит намного больше данных, чем в другую.
Он неидеален, но всё работает. 256-байтная страница разбивается на четыре сегмента, каждый из которых передаётся по радиоканалу в виде пакета. Пакет вмещает до 125 байт данных плюс один байт — длина и два — CRC. Так что фрагменты длиной по 64 байта вместе с номерами страниц и сегментов (от 0 до 3) туда помещаются. В принимающем устройстве предусмотрена переменная, позволяющая отследить, сколько сегментов принято, и когда приходят все четыре, на передающее устройство идёт подтверждение, что принята вся страница. Нет подтверждения (CRC не совпало) — отправляем всю страницу заново. Скорость при этом получается даже больше, чем при передаче по кабелю. Смотрите:
Но вообще-то, надо бы предусмотреть удобный способ подключения к устройствам кабеля для заливки скетчей и по нему. Например, поместить внутрь такой преобразователь интерфейсов на CP2102, как на фото, и приклеить его к плате так, чтобы он выдерживал усилие при подключении и отключении Micro USB-кабеля.
Также в нём есть 3,3-вольтовый стабилизатор (и как его применить в устройстве с 6-вольтовым питанием — если только там есть такой же стабилизатор, и можно добавить два диода, чтобы автоматически выбирать, от какого из них будет питаться устройство). С платы преобразователя интерфейса надо выпаять все три светодиода, иначе они будут дополнительно нагружать батарейки при работе от них, а также мешать опросу клавиатуры и работе с флеш-памятью с интерфейсом SPI.
Преследование цели оказалось даже интереснее, чем её достижение (и не надо того анекдота про автобус). Автор узнал много нового о загрузчиках для AVR, флеш-памяти с интерфейсом SPI, протоколе STK500 и стандарте 802.15.4.
Весь остальной код в дополнение к описанной выше библиотеке —
Источник: habr.com