- Статус
- Оффлайн
- Регистрация
- 28 Авг 2022
- Сообщения
- 113
- Реакции
- 139
Иногда у меня по работе возникает потребность в анализе всяческих штук у железок, да и сами железки тоже анализировать надо. Анализ железяк — это весьма многогранный и комплексный процесс, включающий в себя множество различных этапов по решению какой-либо задачи. Я сегодня хочу остановиться над одним из этапов, не всегда обязательным, но порой весьма важным – анализ сигналов различных протоколов.
Сегодня мы попробуем проанализировать протокол SPI и что читает процессор с SPI чипа. Но для начала немного теории.
Serial Peripheral Interface (или SPI) – это последовательный синхронный интерфейс передачи данных, работает в режиме дуплекса (устройство может в любой момент передавать и принимать информацию).
Суть интерфейса заключается в связывании одного главного устройства (Master) с несколькими (или более) другими, уже ведомыми (Slave) устройствами. Самый банальный пример – микроконтроллер и периферия.
SPI использует четыре пина/линии (ну или цифровых сигнала):
1. CLK (Clock, иногда SCK/SCLK – Serial Clock) – последовательный тактовый сигнал, служащий для передачи данных от ведущего устройства ведомым;
2. MOSI (Master Out Slave In) – сигнал, передающий данные от ведущего к ведомому;
3. MISO (Master In Slave Out) – сигнал, передающий данные от ведомого к ведущему;
4. CS/SS (Chip Select или Slave Select) – выбор чипа/выбор ведомого.
Названия сигналов на схемах может отличаться, но я привёл их стандартные названия.
Процесс передачи данных выглядит весьма простым. Сперва, выбирается кому будет отправлена информация. Это происходит через подачу «низкого сигнала» (то есть, до выбора на пине всегда «высокий сигнал») на линию CS/SS. После того, как ведомый был выбран, на пинах MOSI и MISO появляется сигнал. Как только сигнал появился, ведущий начинает генерировать синхронизирующие импульсы на CLK/SCK линии, это приводит к обмену данными. Передача данных происходит побитово от ведущего по MOSI и от ведомого по MISO, и, как правило, начинается со старших битов (Most Significant Bit, MSB). Эта передача данных будет проводиться до тех пор, пока ведущий не отпустит линию CS/SS.
У SPI есть 4 варианта того, что вообще можно считать за изменение сигнала на линии CS/SS. Для определения изменения сигнала на линии существует комбинация бит CPOL (Clock Polarity) и CPHA (Clock Phase). CPOL – исходный уровень синхронизации, а CPHA – фаза синхронизации, то есть по какому фронту (переключению) сигнала происходит выборка данных.
Если CPOL = 0, то исходное состояние сигнала CLK/SCK – низкое. Если же наоборот, CPOL = 1, то исходное состояние сигнала CLK/SCK – высокое. Если CPHA = 0, то выборка данных происходит по переднему фронту. Если CPHA = 1 – по заднему фронту.
Подготовка
В качестве испытуемого у меня будет SPI чип от Gigadevice - GD25LB64C SOIC8 форм-фактора. Почему он? Его проще всего использовать в качестве экспериментов, как раз таки из-за форм-фактора.
Как же анализировать сигнал? Очень просто, нужно устройство, позволяющее подключаться к пинам железяки. Сегодня мы будем работать с логическим анализатором – это устройство, которое может записывать и отображать последовательность считываемых цифровых сигналов. В качестве логического анализатора у меня 16-канальный DSLogic U3Pro16:
Есть также Saleae, они могут быть дешевле DSLogic. В качестве софтины я буду использовать стандартный DSView, который создавался для работы с DSLogic:
DSView необходимо будет настроить, но для начала нащупаем SPI чип на целевой материнской плате:
Далее начинаются танцы с бубнами – крепление щупов к ножкам чипа. Это весьма медитативное и одновременно раздражающее занятие. Но, спустя какое-то время и это можно порешать:
Я подключаю все пины строго в последовательности как написано в читшите чипа:
То есть, серый щуп (самый ближний) – пин CS#, синий – пин IO1, зелёный – пин IO2, жёлтый (возле зелёного) подключён к плюсу (вообще, его необязательно подключать, это у меня дело привычки), серый (дальний) – IO0, красный – SCLK, жёлтый (возле красного) – пин IO3.
Разберёмся с DSView. У DSLogic есть два режима работы (вообще три, но последний нам не нужен): потоковый и буферизованный. Потоковый режим передаёт данные с устройства на компьютер в режиме реального времени, в то время как буферизованный подержит его какое-то время внутри логического анализатора, пока не закончится запись текущего куска трассы (от нажатия кнопки Start, до кнопки Stop). Режим работы можно выставить во вкладке Options.
Нам весьма важен режим, так как потоковый ограничен частотой в 20МГц, что не очень нам подходит. Дело в том, что у анализатора весьма длинные провода, что повышает сопротивление на них, из-за чего на достаточно низкой частоте могут происходить помехи и нам прилетит мусор. Зато, в буферизованном режиме мы не ограничены 20МГц, так что выбираем его и выставляем 50МГц. А режим выставим «повторяющийся»:
Включаем анализатор и целевой компьютер, чутка подождём и остановим запись. Увидим следующую картину:
Это один из участков нашей записи! Мы видим весьма плотную генерацию синхронизирующего сигнала, какие-то данные на каких-то линиях, а также, что CS# был в высоком сигнале один раз (то есть не использовался какой-то промежуток времени).
Конечно, это круто, но читать проблематично. И, чтоб решить эту проблему, мы можем использовать встроенные декодеры цифрового сигнала! Нажимаем на «Decode» и выбираем SPI Flash (так как мы всё же с чипом работаем). И пытаемся сориентироваться, где кто… Давайте ещё раз поглядим на расположение пинов:
Щупы начинают пронумеровываться с нуля, а значит, что пин CS# - это линия 0 в DSView, то есть серый щуп, красный щуп (пин SCLK) – это линия 5. А где MISO и MOSI? Они не помечаются в читшитах нормально, но, по стандарту – MISO это IO1, а MOSI это IO0. Выставляем в настройках декодера нужные линии (можно ещё вниз прокрутить и поставить в чипах Winbond):
Остальное можно не трогать, по крайней мере, если всё декодируется нормально. В противном случае, нужно обратиться к читшиту чипа. Через какое-то время запись декодируется, и мы увидим на выбранном участке декодированный цифровой сигнал:
Отлично! Мы попали прямиком в команду Fast Read, её номер
Как мы видим, здесь также представлена схема сигнала. Сначала, 8 бит занимает номер команды. После номера команды идёт 24-битный адрес в флэш-памяти, в нашем случае это
Кстати, судя по всему, в чипе первые 15 байт – нули. Данные начинаются с 16 байта, это можно понять по состоянию сигнала в MISO:
Действительно ли по этому адресу располагаются такие данные? В этом можно убедиться, сняв дамп содержимого чипа, что я, собственно, и сделал:
И, да, они совпадают. Получается, что в первую очередь, при загрузке ОС, процессор пытается считать содержимое NVRAM переменных, судя по сигнатуре NVAR.
Или, допустим, по адресу
Quad SPI и Dual SPI
Всё это был обычный SPI, но существуют ещё Dual SPI (DPI) и Quad SPI (QPI). Их основное различие от обычного SPI – скорость. Dual обеспечивает скорость x2 от обычного SPI, а Quad x4 соответственно. Делается это за счёт увеличения пинов/линий. И вот это уже интересно нам (а остальные интересности можно нагуглить), так как сам SPI чип может работать в этих режимах, более того, они могут иметь собственные команды, либо иметь отличия от команд обычного SPI. Например, в QPI команда Fast Read (
Чип может очень часто использовать QPI и DPI. А значит, нам нужно что-то с этим делать! И ответ есть: в декодерах нам необходимо выбрать Smart QSPI и проставить все линии в соответствии с читшитом анализируемого чипа. После же мы увидим ещё один пласт данных:
Теперь мы добавили декодирование QSPI команд. DSView и его декодеры умеют определять, когда используются SPI, а когда QSPI, что весьма удобно и не заставляет лезть в читшит снова и снова.
Сегодня мы попробуем проанализировать протокол SPI и что читает процессор с SPI чипа. Но для начала немного теории.
SPI интерфейс
Serial Peripheral Interface (или SPI) – это последовательный синхронный интерфейс передачи данных, работает в режиме дуплекса (устройство может в любой момент передавать и принимать информацию).
Суть интерфейса заключается в связывании одного главного устройства (Master) с несколькими (или более) другими, уже ведомыми (Slave) устройствами. Самый банальный пример – микроконтроллер и периферия.
SPI использует четыре пина/линии (ну или цифровых сигнала):
1. CLK (Clock, иногда SCK/SCLK – Serial Clock) – последовательный тактовый сигнал, служащий для передачи данных от ведущего устройства ведомым;
2. MOSI (Master Out Slave In) – сигнал, передающий данные от ведущего к ведомому;
3. MISO (Master In Slave Out) – сигнал, передающий данные от ведомого к ведущему;
4. CS/SS (Chip Select или Slave Select) – выбор чипа/выбор ведомого.
Названия сигналов на схемах может отличаться, но я привёл их стандартные названия.
Процесс передачи данных выглядит весьма простым. Сперва, выбирается кому будет отправлена информация. Это происходит через подачу «низкого сигнала» (то есть, до выбора на пине всегда «высокий сигнал») на линию CS/SS. После того, как ведомый был выбран, на пинах MOSI и MISO появляется сигнал. Как только сигнал появился, ведущий начинает генерировать синхронизирующие импульсы на CLK/SCK линии, это приводит к обмену данными. Передача данных происходит побитово от ведущего по MOSI и от ведомого по MISO, и, как правило, начинается со старших битов (Most Significant Bit, MSB). Эта передача данных будет проводиться до тех пор, пока ведущий не отпустит линию CS/SS.
У SPI есть 4 варианта того, что вообще можно считать за изменение сигнала на линии CS/SS. Для определения изменения сигнала на линии существует комбинация бит CPOL (Clock Polarity) и CPHA (Clock Phase). CPOL – исходный уровень синхронизации, а CPHA – фаза синхронизации, то есть по какому фронту (переключению) сигнала происходит выборка данных.
Если CPOL = 0, то исходное состояние сигнала CLK/SCK – низкое. Если же наоборот, CPOL = 1, то исходное состояние сигнала CLK/SCK – высокое. Если CPHA = 0, то выборка данных происходит по переднему фронту. Если CPHA = 1 – по заднему фронту.
Подготовка
В качестве испытуемого у меня будет SPI чип от Gigadevice - GD25LB64C SOIC8 форм-фактора. Почему он? Его проще всего использовать в качестве экспериментов, как раз таки из-за форм-фактора.
Как же анализировать сигнал? Очень просто, нужно устройство, позволяющее подключаться к пинам железяки. Сегодня мы будем работать с логическим анализатором – это устройство, которое может записывать и отображать последовательность считываемых цифровых сигналов. В качестве логического анализатора у меня 16-канальный DSLogic U3Pro16:
Есть также Saleae, они могут быть дешевле DSLogic. В качестве софтины я буду использовать стандартный DSView, который создавался для работы с DSLogic:
DSView необходимо будет настроить, но для начала нащупаем SPI чип на целевой материнской плате:
Далее начинаются танцы с бубнами – крепление щупов к ножкам чипа. Это весьма медитативное и одновременно раздражающее занятие. Но, спустя какое-то время и это можно порешать:
Я подключаю все пины строго в последовательности как написано в читшите чипа:
То есть, серый щуп (самый ближний) – пин CS#, синий – пин IO1, зелёный – пин IO2, жёлтый (возле зелёного) подключён к плюсу (вообще, его необязательно подключать, это у меня дело привычки), серый (дальний) – IO0, красный – SCLK, жёлтый (возле красного) – пин IO3.
Разберёмся с DSView. У DSLogic есть два режима работы (вообще три, но последний нам не нужен): потоковый и буферизованный. Потоковый режим передаёт данные с устройства на компьютер в режиме реального времени, в то время как буферизованный подержит его какое-то время внутри логического анализатора, пока не закончится запись текущего куска трассы (от нажатия кнопки Start, до кнопки Stop). Режим работы можно выставить во вкладке Options.
Нам весьма важен режим, так как потоковый ограничен частотой в 20МГц, что не очень нам подходит. Дело в том, что у анализатора весьма длинные провода, что повышает сопротивление на них, из-за чего на достаточно низкой частоте могут происходить помехи и нам прилетит мусор. Зато, в буферизованном режиме мы не ограничены 20МГц, так что выбираем его и выставляем 50МГц. А режим выставим «повторяющийся»:
Включаем анализатор и целевой компьютер, чутка подождём и остановим запись. Увидим следующую картину:
Это один из участков нашей записи! Мы видим весьма плотную генерацию синхронизирующего сигнала, какие-то данные на каких-то линиях, а также, что CS# был в высоком сигнале один раз (то есть не использовался какой-то промежуток времени).
Конечно, это круто, но читать проблематично. И, чтоб решить эту проблему, мы можем использовать встроенные декодеры цифрового сигнала! Нажимаем на «Decode» и выбираем SPI Flash (так как мы всё же с чипом работаем). И пытаемся сориентироваться, где кто… Давайте ещё раз поглядим на расположение пинов:
Щупы начинают пронумеровываться с нуля, а значит, что пин CS# - это линия 0 в DSView, то есть серый щуп, красный щуп (пин SCLK) – это линия 5. А где MISO и MOSI? Они не помечаются в читшитах нормально, но, по стандарту – MISO это IO1, а MOSI это IO0. Выставляем в настройках декодера нужные линии (можно ещё вниз прокрутить и поставить в чипах Winbond):
Остальное можно не трогать, по крайней мере, если всё декодируется нормально. В противном случае, нужно обратиться к читшиту чипа. Через какое-то время запись декодируется, и мы увидим на выбранном участке декодированный цифровой сигнал:
Отлично! Мы попали прямиком в команду Fast Read, её номер
0Bh. Что делает эта команда? Ну, очевидно, читает данные с SPI чипа, но на частоте выше, чем обычная команда Read. Обратимся к мануалу Gigadevice и убедимся, что команда распознана правильно:
Как мы видим, здесь также представлена схема сигнала. Сначала, 8 бит занимает номер команды. После номера команды идёт 24-битный адрес в флэш-памяти, в нашем случае это
0. Затем же, генерируется dummy-байт, а только после начинают считываться данные, которые начинаются со старшего бита.Кстати, судя по всему, в чипе первые 15 байт – нули. Данные начинаются с 16 байта, это можно понять по состоянию сигнала в MISO:
Действительно ли по этому адресу располагаются такие данные? В этом можно убедиться, сняв дамп содержимого чипа, что я, собственно, и сделал:
И, да, они совпадают. Получается, что в первую очередь, при загрузке ОС, процессор пытается считать содержимое NVRAM переменных, судя по сигнатуре NVAR.
Или, допустим, по адресу
0xF00 процессор также читает какие-то данные:
Quad SPI и Dual SPI
Всё это был обычный SPI, но существуют ещё Dual SPI (DPI) и Quad SPI (QPI). Их основное различие от обычного SPI – скорость. Dual обеспечивает скорость x2 от обычного SPI, а Quad x4 соответственно. Делается это за счёт увеличения пинов/линий. И вот это уже интересно нам (а остальные интересности можно нагуглить), так как сам SPI чип может работать в этих режимах, более того, они могут иметь собственные команды, либо иметь отличия от команд обычного SPI. Например, в QPI команда Fast Read (
0Bh) выглядит следующим образом:
Чип может очень часто использовать QPI и DPI. А значит, нам нужно что-то с этим делать! И ответ есть: в декодерах нам необходимо выбрать Smart QSPI и проставить все линии в соответствии с читшитом анализируемого чипа. После же мы увидим ещё один пласт данных:
Теперь мы добавили декодирование QSPI команд. DSView и его декодеры умеют определять, когда используются SPI, а когда QSPI, что весьма удобно и не заставляет лезть в читшит снова и снова.
Послесловие
Небольшой спонтанный гайд по использованию логического анализатора. Правда, идея спонтанная. На самом деле, примерно подобным образом анализируются все цифровые сигналы (например, I2C, UART), если в этом есть необходимость. Данный небольшой гайд предназначен для ознакомления с работой с логическим анализатором и софтинами под них (DSView, Saleae Logic 2, Sigrok), а также кому интересно что-то хардварное.