Пишемо OTA-завантажувач для ATmega128RFA1 (у складі пристрою Smart Response XE)

Пишемо OTA-завантажувач для ATmega128RFA1 (у складі пристрою Smart Response XE)

Все почалося з придбання автором на вторинному ринку цікавого пристрою Smart Response XE (короткий опис). Призначено воно для шкіл: кожен учень у класі отримує по девайсу, схожому на електронну записник або перекладач дев'яностих, учитель ставить запитання, і учні набирають на клавіатурах пристроїв відповіді, що надходять по радіоканалу (802.15.4) до приймача, підключеного до учителя.

Підтримка цих пристроїв припинена кілька років тому, і те, що школи закуповували по 100-200 доларів за штуку, тепер спливає на eBay по 10 і менше. «Залізо» там дуже підходить для гіковських дослідів:

  • клавіатура на 60 клавіш
  • дисплей з роздільною здатністю 384×136, 2 біти на піксель — аналогічно БК, CGA, але 4 не кольори, а градації яскравості
  • мікроконтролер ATmega128RFA1 (128 кБ флеш-пам'яті, 4 кБ ПЗУ, 16 кБ ОЗУ, приймач стандарту 802.15.4)
  • зовнішня (стосовно мікроконтролера, а не всього пристрою) флеш-пам'ять на 1 мегабіт (128 кілобайт) з інтерфейсом SPI
  • відсік для 4 елементів ААА.

За назвою мікроконтролера зрозуміло, що він відноситься до сімейства AVR, а значить, зробити пристрій Arduino-сумісним - завдання більш ніж тривіальне.

З новини на Hackaday автор дізнався, що це вже зробили (за цим посиланням розказано, що куди підключати), отримавши можливість запускати ігри для Arduboy:


Але автора більше цікавить можливість не пограти на пристрої, а вивчити:

  • флеш-пам'ять із послідовним інтерфейсом SPI
  • завантажувачі для AVR
  • стандарт 802.15.4

Автор почав із написання бібліотеки (GPL v3), що дозволяє ініціалізувати дисплей, виводити текст та прямокутники, а також отримувати доступ до флеш-пам'яті з інтерфейсом SPI. Потім він почав вигадувати ідеї практичного використання пристрою: кишеньковий VT-100-сумісний термінал, розраховані на багато користувачів ігри. Переробивши три девайси, він вирішив «навчити» їх отримувати скетчі «по повітрю». Що було б не тільки цікаво, але й дуже зручно: корпус пристрою щоразу відкривати важко, а під кришкою відсіку батареї знаходяться тільки отвори, що дозволяють підключати до плати JTAG-програматор.

Пишемо OTA-завантажувач для ATmega128RFA1 (у складі пристрою Smart Response XE)

Цього достатньо, щоб залити завантажувач Arduino, але не скетч — послідовний порт туди не виведений, без відкриття корпусу все одно не обійтися. Також лінії TX0 і RX0 першого послідовного порту поєднані з лініями опитування матриці клавіатури, а саме тими, якими йде опитування функціональних клавіш по сторонах від дисплея. Але що вдієш — автор зробив ось що:

Пишемо OTA-завантажувач для ATmega128RFA1 (у складі пристрою Smart Response XE)

Туди він вивів лінії JTAG, і тепер відсік батарей відкривати не обов'язково. А щоб можна було заливати і скетчі, вивів на цей же роз'єм і обидва послідовні порти, додавши також вимикач, тому що при встановлених батарейках пристрій по-іншому фізично вимкнути неможливо.

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

Arduino IDE для заливки скетчів використовує програму avrdude. Вона взаємодіє з мікроконтролером за протоколом STK500, що дозволяє передавати файли в обидві сторони. Він погано сумісний із каналами, де можливі змінні затримки, спотворення та втрата даних. Якщо в послідовному каналі щось відходить або шарудить, можна збожеволіти в пошуках причини. Одного разу автор промучився півдня, поки не зрозумів, що справа в поганому кабелі, а також примхливому перетворювачі інтерфейсу CP2102. Навіть мікроконтролер із вбудованим перетворювачем інтерфейсу, наприклад, ATmega32u4, може іноді так «пустувати». Кожен користувач Arduino помічав, що помилки при заливанні скетчів не такі вже й рідкісні. Іноді запис відбувається нормально, а при перевірочному зчитуванні виявляється помилка. Це не означає, що помилка була під час запису - збій був при читанні. А тепер уявіть, що при роботі «по повітрю» відбуватиметься те саме, але набагато частіше.

Перепробувавши різні способи подолання цієї проблеми, автор вигадав таке. У пристрою є 128-кілобайтна флеш-пам'ять з інтерфейсом SPI - приймаємо дані по дротах (пам'ятаємо, що один девайси з роз'ємом на боці автора вже є), використовуємо цю пам'ять як буфер, і по радіоканалу відправляємо дані в інший пристрій. Таке привіт від Cybiko.

Після написання коду для роботи з радіоканалом, а також шрифту, завантажувач став довшим за 4 кілобайти. Тому значення HFUSE довелося змінити з 0xDA to 0xD8. Тепер завантажувач може бути довжиною до 8 кілобайт, а початкова адреса стала дорівнює 0x1E000. Це відображено в Makefile, але має бути враховано і при заливанні завантажувача за допомогою avrdude.

Приймач стандарту 802.15.4 в ATmega128RFA1 спочатку призначений для роботи по протоколу ZigBee, який досить складний, тому автор вирішив натомість просто передавати пакети. Це в ATmega128RFA1 реалізовано апаратно, так що коду потрібно небагато. Також для простоти автор вирішив використати фіксований канал, не даючи вибрати його навіть вручну. Стандарт 802.15.4 підтримує 16 каналів із номерами від 11 до 26. Вони досить забиті, деякі також перекривають канали WiFi (червоним позначені канали ZigBee, синім, зеленим та жовтим – WiFi).

Пишемо OTA-завантажувач для ATmega128RFA1 (у складі пристрою Smart Response XE)

Виявилося, що найменш схильні до перешкод від WiFi канали 15 і 26. Другий з них автор і вибрав. Дисклеймер: перекладач не знає, чи можна так спрощувати ZigBee. Можливо, варто ще трохи попрограмувати та реалізувати його повністю?

На першому з пристроїв треба реалізувати кінцевий автомат, який передає дані протоколу STK500. У більшості своїй повідомлення, що передаються і приймаються самодостатні, але деякі прив'язані до минулих каналом раніше. Опис діалогу наведено тут.

Важливою складовою цього діалогу є передача пакетів, призначених для запису флеш-пам'ять пристрою призначення. У простих мікроконтролерів сімейства AVR розмір сторінки становить 128 байт, але у ATmega128RFA1 - 256. А у тієї флеш-пам'яті, яка підключається за протоколом SPI, він такий самий. Програма в першому пристрої при заливці скетчу не передає його відразу в друге, а пише його в пам'ять. Коли Arduino IDE перевіряє правильність запису, йому відправляють те, що туди записалося. Тепер треба передати отримані дані радіоканалу в другий пристрій. При цьому перемикання з прийому на передачу та назад відбувається досить часто. Протокол STK500 байдужий до затримок, але не терпить втрати даних (дивно, а вище сказано, що затримки передачі даних теж позначаються). А втрати під час бездротової передачі неминучі. В ATmega128RFA1 вбудована апаратна реалізація повторних запитів при сумнівах у правильності передачі, але автор вирішив реалізувати те саме програмно самостійно. Він розробив протокол, за якого в один бік проходить набагато більше даних, ніж у інший.

Він неідеальний, але все працює. 256-байтна сторінка розбивається на чотири сегменти, кожен з яких передається по радіоканалу у вигляді пакета. Пакет вміщує до 125 байт даних плюс один байт – довжина та два – CRC. Так що фрагменти завдовжки по 64 байти разом із номерами сторінок та сегментів (від 0 до 3) туди поміщаються. У пристрої, що приймає, передбачена змінна, що дозволяє відстежити, скільки сегментів прийнято, і коли приходять всі чотири, на передавальний пристрій йде підтвердження, що прийнята вся сторінка. Немає підтвердження (CRC не збіглося) - надсилаємо всю сторінку заново. Швидкість при цьому виходить навіть більшою, ніж при передачі кабелем. Дивіться:


Але взагалі-то, треба було б передбачити зручний спосіб підключення до пристроїв кабелю для заливки скетчів і по ньому. Наприклад, помістити всередину такий перетворювач інтерфейсів на CP2102, як на фото, і приклеїти його до плати так, щоб він витримував зусилля під час підключення та відключення Micro USB-кабелю.

Пишемо OTA-завантажувач для ATmega128RFA1 (у складі пристрою Smart Response XE)

Також у ньому є 3,3-вольтовий стабілізатор (і як його застосувати у пристрої з 6-вольтовим живленням - якщо тільки там є такий же стабілізатор, і можна додати два діоди, щоб автоматично вибирати, від якого з них буде живитись пристрій). З плати перетворювача інтерфейсу треба випаяти всі три світлодіоди, інакше вони додатково навантажуватимуть батарейки при роботі від них, а також заважатимуть опитування клавіатури і роботі з флеш-пам'яттю з інтерфейсом SPI.

Переслідування мети виявилося навіть цікавішим, ніж її досягнення (і не треба того анекдоту про автобус). Автор дізнався багато нового про завантажувачі для AVR, флеш-пам'яті з інтерфейсом SPI, протокол STK500 і стандарт 802.15.4.

Весь решта коду на додаток до описаної вище бібліотеки. тут, і він також під GPL v3. Твіттер автора тут.

Джерело: habr.com

Додати коментар або відгук