Главная » Хабрахабр » [Перевод] Взлом дешёвого фитнес-браслета

[Перевод] Взлом дешёвого фитнес-браслета

Это перевод. Статья опубликована 27 мая 2018 года


Фитнес-трекер до и после разборки

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

  • действительно маленький форм-фактор (примерно 15×40 мм);
  • Bluetooth low energy (BLE);
  • OLED-дисплей (96×32 пикселя);
  • аккумулятор;
  • USB-зарядка;
  • акселерометр;
  • вибромотор;
  • цена около $10 (!).

Снаружи на задней панели единственный идентификатор — это наклейка «FCC ID: 2AHFTID115». Если погуглить, то это вроде как соответствует устройству ID115 и можно даже найти несколько фотографий его внутренностей. Оглядываясь назад, на одной из этих фотографий, если сильно постараться, можно разглядеть название самой крупной интегральной схемы (IC): N51822. Это говорит о том, что здесь может быть микроконтроллер (MCU) nRF51822 от Nordic, 32-битный процессор ARM M0 со встроенной поддержкой BLE, который теоретически достаточно легко запрограммировать на другие вещи, которые должен делать браслет.

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

Чёрная пластиковая крышка приклеена к серому заднику. Открыть корпус оказалось не так-то просто. После вскрытия я убедился, что там действительно nRF51822. Я попробовал фен, чтобы размягчить клей, и терпеливо резал его маленьким ножичком, стараясь не слишком повредить пластик. Имейте в виду, что есть варианты. Позже я купил практически идентичный браслет с MCU от Texas Instrument.


nRF51822 и шариковая ручка для масштаба

В документации говорится, что чип можно запрограммировать/отладить с помощью двухконтактного интерфейса ARM Serial Wire Debug (SWD). Если мы хотим установить канал коммуникации с чипом, то это означает две вещи:

  • Нам понадобится программатор SWD (например, Segger J-Link).
  • Нам понадобится доступ к двум контактам SWD на микроконтроллере, а именно SWDIO (данные) и SWDCLK (тактовые импульсы).

К счастью, на плате есть несколько доступных контактных площадок. Хотя их существование явно объясняется необходимостью отладки, тестирования и проверки, я предпочитаю думать, что какой-то классный инженер оставил их там как маленькие подарки для таких как мы. Не все они должным образом помечены, поэтому предлагаю такие коды:

Шариковая ручка для масштаба и полупроизвольные названия для открытых контактных площадок
Передняя и обратная стороны печатной платы.

С помощью такого же дешёвого USB-микроскопа я сделал несколько снимков передней и обратной сторон платы и попытался отследить дорожки от микроконтроллера до контактных площадок.


Дорожки к контактам SWDIO и SWDCLK на передней и задней сторонах платы

По этим фотографиям можно отследить дорожки от контактов SWDIO и SWDCLK на чипе до контактных площадок IO и CLK. Обратите внимание, что это многослойная печатная плата со сквозными отверстиями, поэтому следует проверять дорожки с обеих сторон платы. Теперь можно подготовить нашу первую таблицу сопоставления: Так мы убедимся, что пометка CLK на плате соответствует SWDCLK на MCU, а непомеченный контакт — это вывод SWDIO.

Вывод nRF51822

Площадка

Описание

SWDIO

IO

Штырь данных для программирования SWD

SWDCLK

CLK

Штырь тактовой частоты для программирования SWD

Получив доступ к двум контактным площадкам SWD, я припаял очень тонкие проводки к ним и ко всем остальным доступным контактам.

Следующая задача — попытаться запрограммировать устройство на какую-нибудь задачу. Чтобы запустить простейшую программу, мы должны убедиться в следующем:

  • Мы правильно отследили контакты SWDIO/SWDCLK.
  • Программатор SWD работает, и компьютер может подавать команды.
  • Мы можем скомпилировать программу Arm и корректно использовать Nordic SDK.
  • Мы можем прошить скомпилированную программу в чип.
  • Чип правильно работает и загружает нашу программу.

В качестве “hello, world” в данном случае может выступить программа, включающая и выключающая светодиод. И даже это не элементарно, потому что на плате нет встроенного светодиода, а если добавить внешний, то всё равно нужно выяснить, к чему его подключать. Это добавляет ещё одно измерение в пространственную модель проблемы. Согласно теореме об отсутствии бесплатного сыра я просто подключил два светодиода на контакты P1 и P2 с надеждой, что мы сможем добраться до этих контактных площадок с MCU.


День плохих проводов

Если вы на macOS и используете Homebrew, то ищите формулу Cask в caskroom/drivers/segger-jlink. Драйверы и программы командной строки для программатора J-Link SWD лежат на сайте Segger. Связь с программатором SWD устанавливается из утилиты командной строки JLinkExe.

3. Затем я скачал Nordic nRF5 SDK (я использую версию 12. Из примеров SDK понятно, что нам понадобится компилятор, способный компилировать программы Arm. 0). Поэтому я установил ещё gcc-arm-embedded (тоже доступный на Homebrew).

SDK предварительно сконфигурирован для нескольких вариантов таких плат. Изучив документацию SDK и форумы разработчиков Nordic, я выяснил, что их SDK чаще всего используют с платами разработки вроде этой. Поскольку мы контачим непосредственно с контроллером, то придётся настроить некоторые параметры SDK.

На видео показаны два мигающих светодиода. Я потратил много времени на понимание экосистемы nRF5, но в конце концов всё-таки смог запустить программу на чипе! Одним из самых главных секретов стало то, что на самом деле есть несколько вариантов nRF51822, а в моём всего лишь 16 КБ памяти. На данном этапе я создал репозиторий Github и сбросил туда программу с рабочим Makefile. Так что пришлось ещё подправить скрипт компоновщика.

Как я уже говорил, задача с миганием светодиодов предусматривала некоторые надежды и метод тыка, какие из контактов MCU ведут к P1 и P2, где подключены светодиоды. Простейшая стратегия — подключать все штырьки по очереди и поочередно подавать высокое и низкое напряжение. К моему удивлению, оба светодиода загорелись! Ещё больше я удивился, когда заработал вибромотор!

Итак, метод тыка дополнил таблицу:

Вывод nRF51822

Площадка

Описание

P0.30

P1

Цифровой ввод-вывод общего назначения

P0.00

P2

Цифровой ввод-вывод общего назначения

P0.01

-

Вибродвигатель

Способность передавать данные на компьютер незаменима при отладке. Программатор J-Link поддерживает передачу в реальном времени (RTT) как для отправки, так и для получения данных с чипа. Чтобы использовать RTT, нужно сделать #include "SEGGER_RTT.h" и вызвать SEGGER_RTT_WriteString(). Для получения данных на компьютере вызовите интерфейс командной строки jlinkrttlogger, который поставляется в комплекте J-Link.
Ещё одна сложная задача — заставить работать OLED. В самых распространённых OLED на рынке работает драйвер/контроллер ssd1306, и обычно коммуникация с MCU осуществляется по последовательному интерфейсу, используя или SPI, или I²C. Вот пример от Adafruit.

И размер 96×32 у него нестандартный. Я не нашёл такой дисплей ни в одном из обычных магазинов. Поиск по идентификатору QT1316P01A на дисплее выдаёт китайские сайты типа Aliexpress, но там нет никакой документации, кроме наименований штырей:


Именования штырей OLED с Aliexpress

Если дорожки между тремя выводами nRF51822 и этими тремя выводами OLED, то мы сделаем шаг вперёд. Если список не врёт, то контакты SCL, SDA и RES# указывают нам, что это вариант I²C. Вернёмся к микроскопу.


Дорожки контактов данных OLED

Обновляем таблицу соответствий:

Вывод nRF51822

Площадка

Описание

P0.21

-

Вывод OLED SDA

P0.22

-

Вывод OLED SCL

P0.24

-

Вывод OLED RES#

Протокол I²C гораздо более продвинутый, чем какой-нибудь простой последовательный протокол вроде UART. Одно из преимуществ в том, что он поддерживает по несколько устройств master и slave на одной шине. Это немного усложняет дело: как минимум, нужно сказать MCU, для какого slave подаются команды. Так что на высоком уровне кроме физических контактов есть ещё «логический» адрес OLED-дисплея.

Он опрашивает со все возможные логические адреса и сообщает, если там что-то установлено. К счастью, один из примеров в nRF5 SDK — это сканер I²C. Он выдаёт такой лог: Моя модифицированная версия здесь.

$ make
# ...
$ make flash
# ...
$ make log
# ...
TWI scanner.
TWI device detected at 0x3c.

У нас есть веские основания полагать, что дисплей правильно идентифицирован и это действительно вариант I²C. Отличная новость! Поиск в гугле говорит, что 0x3c — типичный адрес для таких устройств.

На этом уровне нет абстракции через библиотеку. Теперь мы готовы отправить какие-то пиксели на дисплей. Процесс состоит из последовательности команд конфигурации, которые устанавливают ориентацию дисплея, режим записи, размер и т.д. В документации ssd1306 можно найти низкоуровневый способ передачи данных. Затем в графическую память дисплея (GDDRAM) отправляется последовательность байт, которые отображаются на экране.

Именно на это ушла львиная часть времени в данном проекте. Для правильной конфигурации я изучил библиотеку ssd1306 от Adafruit и попытался эмулировать подобные команды. Тем не менее, оно работает! Узнать все детали оказалось весьма трудоёмким занятием, и всё равно некоторые вещи я не могу объяснить.


Отображение жёстко закодированного растрового рисунка

Код этого примера здесь.

Так что страницы по 8 пикселей в высоту. С такими настройками дисплей делится на 4 строки (страницы) и 96 столбцов. Второй байт займёт второй столбец, затем третий и так далее, вплоть до 96-го столбца, когда он возвращается и начинает с первого столбца на второй странице. Первый отправленный байт расположится «вертикально» в первом столбце первой страницы.

Как показано на видео, наблюдаемое поведение отличается: сначала заполняются нечётные столбцы, затем чётные, и только потом он возвращается ко второй странице. Таково ожидаемое поведение.

В конце концов, я проглотил свою гордость и всё-таки реализовал в программе такую странную логику рендеринга, чтобы закончить на этом. Я потратил немало времени, чтобы понять причину столь глупого поведения дисплея, а затем ещё некоторое время на настройку конфигурации, чтобы исправить это.

Копаясь в библиотеке ssd1306 от Adafruit для Arduino, я всё время думал, что хорошо бы иметь способ «имитации» специфичных битов Arduino, чтобы протестировать их на nRF51822. Оказывается, гораздо более опытные люди тоже думали на эту тему — именно это делает удивительный проект sandeepmistry/arduino-nRF5. Он реализует основные библиотеки Arduino с помощью nRF5 SDK.

Я форкнул проект и добавил поддержку платы из нашего браслета. С помощью этого проекта мы можем открыть Arduino IDE, выбрать плату nRF5 — и использовать богатую экосистему Arduino. Его можно выбрать в раскрывающемся меню Tools > Board > ID115 Fitness Bracelet (nRF51822).


Библиотека ssd1306 от Adafruit в оригинальном виде (вверху) и с патчем (внизу)

К моему удивлению и облегчению, произошло то же самое странное поведение с заполнением сначала нечётных, а потом чётных столбцов OLED! Это также означает, что теперь мы можем использовать библиотеку OLED от Adafruit. По сравнению с низкоуровневым подходом, теперь у нас есть доступ к разнообразным классным абстракциям, например, выводу текста: Я с удовольствием форкнул библиотеку и внедрил тот же хак.


Более привычный “Hello, world!”

Кроме цифровых сигналов «включить/выключить», у nRF51822 есть 10 контактов для аналогового ввода. Это полезно, например, для чтения текущего заряда аккумулятора. Судя по документации, чтение аналоговых контактов выдаёт 10-битное значение. Поэтому если на входе находится 0V, то мы прочитаем 0, а если там VCC, мы прочитаем 1023 с промежуточными значениями между ними.

Я периодически считывал значения аналоговых входов и составил графики самых интересных сигналов:


Эффект встряхивания платы и зарядки аккумулятора по данным с аналоговых входов

05 относится к заряду аккумулятора, потому что значение увеличивается и уменьшается по мере зарядки и разрядки. Я убеждён, что контакт P0. 26 подключен к одному из выходов акселерометра, поскольку он сходит с ума при встряхивании платы. Подозреваю, что контакт P0. 03 и P0. Контакты P0. Например, на первом графике обратите внимание, как уровень заряда батареи (вывод 5) изменяется, когда акселерометру требуется больше энергии. 04 тоже могут быть подключены к различным выходам акселерометра, но здесь на сигнал со входа скорее всего накладывается некий эффект второго порядка. Это пример эффекта второго порядка.

Исходные данные и скрипт построения графика здесь. Код можно найти в этом наброске. Теперь можно добавить несколько строк в нашу таблицу соответствия:

Вывод nRF51822

Площадка

Описание

P0.05

-

Аналоговый вход — связан с зарядом батареи

P0.26

-

Аналоговый вход — одна ось акселерометра

P0.03

-

Аналоговый вход — одна ось акселерометра (вероятно)

P0.04

-

Аналоговый вход — одна ось акселерометра (вероятно)

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

Код лежит здесь.

Вывод nRF51822

Площадка

Описание

P0.10

-

Цифровой вход — встроенная кнопка

Функциональность BLE на чипах nRF5 реализована через нечто под названием SoftDevice. Это предварительно скомпилированный двоичный файл со стеком BLE. Он прошивается независимо от приложения. Есть много версий SoftDevice, в зависимости от версии SDK и версии чипа.

Она показывает, с какой SDK поставляются разные версии чипа — и какая там стоит версия SoftDevice. В документации приводится некая матрица зависимости (к сожалению, на неё нельзя поставить прямую ссылку). В нашем случае на чипе стоит отметка QFAAH0, у этой микросхемы 256 КБ флэш-памяти, 16 КБ оперативной памяти и заявлена совместимость с SoftDevice s130.

3 уже содержит несколько примеров использования SoftDevice s130. Мой SDK версии 12. После загрузки и инициализации двоичный файл SoftDevice перейдёт к этому адресу и передаст управление нашей программе. По сравнению с предыдущими программами, которые прямо зашиваются в микросхемы с адреса 0x0, теперь нужно прошить SoftDevice с адреса 0x0, а саму программу — с адреса 0x1b000. Наблюдаемое поведение не изменилось, разве что следует заранее прошить SoftDevice: Чтобы проиллюстрировать, я взял тот же пример с морганием светодиодов, но изменил его для прошивки SoftDevice (код).

$ make
# ...
$ make flash-softdevice
# ...
$ make flash
# ...
$ make log
# ...
Hello, world!

Устройство только транслирует своё присутствие. Пожалуй, самое простое приложение для Bluetooth — превращение устройства в маячок. Он предполагает, что SoftDevice s130 уже прошит. Один из таких примеров есть в SDK под названием ble_app_beacon.

Кроме настройки размера оперативной памяти (это знание тяжко мне далось в примере со светодиодами), выявилась ещё одна трудно отслеживаемая проблема. Здесь тоже низкоуровневая коммуникация с чипом всё усложняет по сравнению с программированием через SDK. В примерах SDK предполагается наличие внешнего кварцевого генератора. Как оказалось, для выполнения чувствительных ко времени задач стек BLE использует генератор тактовой частоты. Исходный код маячка здесь. Когда я это понял после тысяч попыток printf, то изменил флаг конфигурации на использование синтетического генератора тактовых импульсов, и проблема решилась.

Когда пример BLE заработал с nRF5 SDK, зная о ловушках с оперативной памятью и генератором, я снова посмотрел на среду Arduino. И опять там оказался славный проект sandeepmistry/arduino-BLEPeripheral (от того же парня, что и arduino-nRF5!), который обеспечивает отличные абстракции поверх внутренней настройки BLE.

Автор проекта arduino-nrf5 потратил время и добавил конфигурацию всех плат и настроек, так что теперь выбор правильного генератора тактовых импульсов для SoftDevice сводится к простому выбору из выпадающего меню Tools > Low Frequency Clock > Synthesized. К моему удивлению, не пришлось даже форкать библиотеку. Я по-быстрому написал пример с включением зелёного светодиода по Bluetooth (с этим приложением). Потрясающе. Его работа показана на видео.

После возни с этой платой бесчисленные часы в течение нескольких недель у меня чешутся руки засунуть её подальше за стиральную машину и забыть на некоторое время.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Сетевой дайджест: 20 экспертных материалов о протоколах, стандартах и информационной безопасности

В эту подборку мы включили свежие посты, подготовленные специалистами компании VAS Experts. Главные темы подборки — сетевые протоколы, 5G и информационная безопасность. Под катом вы также найдете ряд рекомендаций по построению сетей операторов связи. / Pxhere / PD Про ИБ ...

[Перевод] Забудьте о мегаструктурах инопланетян: новые наблюдения объясняют поведение звезды Табби одной только пылью

Художественное изображение KIC 8462852, яркость которой за последние несколько лет менялась необычным образом Когда планета проходит перед её родительской звездой, если смотреть с нашей точки зрения, часть света звезды на некоторое время исчезает. Научная охота за планетами в XXI веке ...