Стандарты в любой индустрии — это инструмент, позволяющий решить сразу несколько задач: ускорить и упростить разработку, унифицировать и формализовать процессы и получаемые артефакты, обеспечить прогнозируемый уровень качества решения, совместимость одного продукта с другими и взаимозаменяемость деталей и узлов от разных производителей, снизить стоимость производства и эксплуатации и т. д.
Низкоуровневые стандарты обмена в вычислительной технике — не исключение. Однако, главный шаг в установлении стандарта – это не выпуск документа и объявление его стандартом. В первую очередь, это ознакомление с ним как можно большего числа инженеров-разработчиков, производственников, эксплуатационников.
Эта статья ориентирована на специалистов по вычислительной технике, программистов, так или иначе имеющих дело с протоколами обмена данными нижнего уровня. Предполагается, что читатель знаком с терминологией i2c или готов заполнить пробелы, используя приведенные в конце статьи ссылки. Материал предназначен для предварительного ознакомления с достаточно новым протоколом i3c, который приходит на замену широко используемому i2c.
Статья является обзорной, и за кадром остались многие детали: описание обработки ошибок, порядок выборов главного мастера (при наличии нескольких), назначение приоритетов прерываний, конкретные форматы кадров и таймингов на шине и т. д. При практической реализации такие детали правильнее черпать из первоисточника. Тем не менее статья будет полезной для плавного перехода от старого доброго i2c к более современному протоколу i3c, который, видимо, станет основным протоколом такого рода, как минимум, на следующие несколько лет.
Применимость протоколов i2c/i3c
Ниша применения протоколов, подобных i2c/i3c, достаточно широка — датчики, дисплеи, устройства управления памятью, чипы других последовательных протоколов и т. п. В общем виде, соединение множества относительно низкоскоростных устройств унифицированным способом в пределах одной системы.
Кратчайший путь к объяснению нового — это возможность опереться на уже имеющееся знание, то есть провести сравнение нового и уже существующего предметов. Для этого нам понадобится некоторая “шкала”. Методики проектирования аппаратных устройств, или средства, используемые в описании программных систем, по отдельности не дают полной картины. С другой стороны, модель OSI хорошо знакома как специалистам по аппаратным средствам, так и программистам. Поэтому, несмотря на то, что семиуровневую модель OSI вряд ли можно назвать общепринятым подходом в отношении протоколов i2c/i3c, мы будем использовать именно ее для целей сравнения этих технологий.
Из спецификаций i2c/i3c мы знаем, что документы регламентируют (согласно классификации OSI) следующие уровни:
- Физический — напряжения, формы и последовательности сигналов, требования к линиям связи.
- Канальный — порядок взаимодействия на шине, формат кадров и логического обмена данными.
- Сетевой — адресацию и маршрутизацию данных.
- Транспортный — управление скоростью и порядком передачи данных.
Являясь протоколами низкого уровня, i2c/i3c не регламентируют ничего, что можно было бы отнести к уровням выше “транспортного”, за исключением определения так называемых CCC-команд, которые можно отнести к сеансовому уровню. В том или ином применении уровни “сеансовый”, “представления” и “прикладной” будут определятся конкретным решением, использующим i2c/i3c, например, SMBus, и конкретной реализацией программного API i2c/i3c.

Несмотря на то, что спецификация i2c практически ставит знак равенства между Ii2c и SMBus, протокол SMBus может быть с равным успехом использован в архитектурах, построенных на других шинах (например, PCI/PCI/e). Но нас не будут интересовать неточности в формулировках спецификации i2c, мы будем использовать классификацию OSI для описания новых возможностей протокола i3c и его сравнения с i2c.
Основные отличия i3c от i2c
В общем случае, устройства i2c вполне совместимы с i3c и могут работать вместе (с некоторыми оговорками, детально описанными в стандарте i3c), используя общую шину. Протокол i2c даже можно рассматривать как подмножество i3c. При этом трафик на скоростях выше возможностей i2c устройства i2c просто «не замечают». Но существуют отличия, которые мы рассмотрим для каждого уровня.

Физический и канальный уровни
В спецификации i3c они описаны довольно подробно. Различия на физическом и канальном уровне между i2c и i3c сводятся к:
- более высокой скорости обмена для i3c — до 12,5-15Мгц;

- меньшему энергопотреблению;

- большей энергоэффективности (отношение энергопотребления к скорости передачи);
- некоторым отличиям в таймингах отправки команд START, адреса, 9-го бита;
- возможности использовать как двухтактный режим выходных каскадов, так и режим с открытым коллектором для i3c, в то время как в схемах i2c, как правило, используется только открытый коллектор;
- использованию другого формата кадра и таймингов на скоростных режимах HDR в случае i3c. При этом для достижения высокой скорости передачи данных i3c использует обе линии (SDA, SCL).
Сетевой уровень
На сетевом уровне i3c использует тот же формат адресов и их диапазон, что и i2c. Однако, ограничений на свободные адреса несколько больше, и часть адресов является служебными. Например, 0x7E и 0x7F являются широковещательными (broadcast) адресами. Ключевая особенность нововведений i3c — специальный механизм динамической адресации. На практике это означает, что ведомые устройства могут менять свой адрес в процессе работы. Смена адреса в i3c важна еще и тем, что от него зависит приоритет устройства на шине, как для приема/передачи, так и для обработки IBI (см. далее) прерываний. Система может реализовывать различные схемы приоритезации трафика, используя адреса как базу приоритетов.
Транспортный уровень
Если на нижних уровнях протоколы практически совпадают по характеристикам (для скоростей ниже HDR), то, начиная с транспортного уровня, различия проявляются в большей степени. Правильнее даже сказать не «различия», а «расширение» протокола. i3c вводит новые скоростные режимы передачи, и, соответственно, новые варианты порядка передачи данных: SDR (Single Data Rate), HDR (High Data Rate), HDR DDR (Double Data Rate), HDR TSP (Ternary Symbol for Pure Bus – троичное кодирование без поддержки устройств i2c) и HDR TSL (Ternary Symbol Legacy-Inclusive-Bus – троичное кодирование с поддержкой устройств i2c на общей шине). К слову, базовая спецификация i3c, на материалах которой основана данная статья, не включает описание этих скоростных режимов. При этом отмечается, что устройства, созданные по данной спецификации, должны различать скоростные режимы и подчиняться общим правилам для сосуществования с более быстрыми устройствами на одной шине.
Ведущее (master) устройство на шине может обращаться одновременно к подчиненным устройствам (slave) как стандарта i2c, так и поддерживающим i3c, но к каждому из них согласно своим правилам. На шине может быть реализовано несколько ведущих устройств, но только одно из них будет главным ведущим. Протокол определяет порядок выбора главного. Кроме того, в процессе работы роли ведущих устройств могут меняться с передачей полномочий главного от одного устройства к другому.
Новый протокол идет существенно дальше i2c: в нем появляются собственные правила управления шиной и устройствами — команды CCC (Common Command Codes) и прерывания IBI (Inband Interrupts).
Рассмотрим общение между ведущим и ведомым устройствами в режиме SDR. Забегая немного вперед, отметим, что каждое ведомое i3c устройство должно иметь некоторый минимальный набор конфигурационных регистров:
- BCR (Bus Characteristics Register) – регистр характеристик шины, обязательный для всех устройств i3c. Определяет роль устройства и его возможности на шине.
- DCR (Device Characteristics Register) – регистр характеристик устройства, также обязательный для всех i3c-совместимых устройств. Описывает класс и тип подключенного устройства — сенсор, гироскоп и т. п.
LVR (Legacy Virtual Register) – виртуальный регистр совместимости для устройств i2c. Каждое устройство i2c на шине i3c должно иметь такой регистр, но за его реализацию может отвечать драйвер, поэтому он виртуальный SDR (Single Data Rate – режим одинарной скорости) – основной протокол (режим) обмена данными в i3c. Он основан на стандартном протоколе i2c с некоторыми отличиями, как правило, на физическом уровне. С программной точки зрения это:
- другая интерпретация 9-го бита в 9-битном слове данных (так называемый T-бит, «transition bit»), которая связана с различной реализацией физических линий обмена данными;
- расширенное толкование сообщения. В i3c сообщение – это все, что передается после команды START (или повторный START) до следующей команды повторного START или STOP;
- изменения в механизме чтения/записи данных. В отличие от i2c, чтение/запись данных в i3c не требует подтверждения после отправки/получения ведомым устройством каждого байта.
Общий формат сообщения SDR выглядит так:
- После команды START на все ведомые устройства i3c отправляется адрес 0x7E (широковещательный адрес i3c). Все они понимают и принимают этот адрес, в отличие от устройств i2c, для которых это зарезервированный адрес, и они на него никак не реагируют.
- За командой START следует адрес ведомого устройства, которому адресовано сообщение. Это может быть как динамический, так и статический адрес, если устройство не поддерживает динамическое назначение адресов (в этом случае динамический адрес может совпадать со статическим). Каждое устройство распознает (и откликается) только свой собственный адрес. Бит RnW адреса указывает последующее направление передачи: чтение (от ведомого к ведущему) или запись (от ведущего к ведомому).
- Далее ведомое устройство ждет или повторный START или STOP, после которого последуют либо данные, либо команда CCC.
Интересно, что после повторного START-а, ведущему не обязательно повторять пролог с использованием широковещательного адреса. Он может выставить на шину адрес другого ведомого устройства и произвести обмен с ним (так как на широковещательный адрес обязаны реагировать все ведомые устройства). При этом направление обмена может быть другим. Процесс может повторяться многократно до отправки ведущим команды STOP. Неудобством можно считать то обстоятельство, что при чтении или записи достаточно большого объема данных, каждый раз операцию необходимо начинать с начала. Это вызвано тем, что, согласно спецификации, устройства самостоятельно увеличивают счетчик отправленных/принятых байт, т.е. в протоколе нет явного позиционирования в массиве данных. Это неудобство, как правило, нивелируется протоколами более высокого уровня, например SMBus.
Еще одним новшеством i3c является введение в посылку байта контрольной суммы. Это актуально для обеспечения надежной передачи данных, учитывая возросшие скорости и длину сообщений без подтверждения. К сожалению, данная возможность не вошла в текущее публичное описание базового протокола i3c
Тем не менее, функций i3c, описанных в публичной версии протокола вполне достаточно, чтобы создавать устройства, способные к работе на шине i3c совместно с устройствами, имеющими проприетарные расширения.
CCC команды
Спецификация MIPI i3c указывает, что формат CCC команд следует правилам протокола SDR. Команды могут быть адресованы:
- всем устройствам на шине — с помощью широковещательной команды (broadcast) CCC: START, 0x7E, код команды CCC, дополнительные данные (если есть), повторный START или STOP;
- конкретному устройству — с помощью адресной (directed) команды: START, 0x7E, код команды CCC, повторный START, адрес получателя, дополнительные данные (если есть), повторный START или STOP (или снова 0x7E)
Направление передачи задается в адресных командах так же, как и для обычного обмена i2c/i3c — битом RnW в адресном байте.
Ведомым устройствам просто отличить широковещательную команду от адресной: адресные команды имеют код превышающий 0x7F (0x80 и далее).
Среди команд CCC можно выделить группы, относящиеся:
- к получению возможностей устройства как ведомого, так и ведущего;
- к получению состояния устройства;
- к управлению адресацией;
- к переключению режимов скорости.
Описание части команд ССС пока не включено в базовую спецификацию i3c – протокол находится в развитии, и некоторые его аспекты уточняются до сих пор. Например, базовая спецификация i3c оставляет «за бортом» рассмотрение вопросов, связанных с устройствами, которые умеют работать в режиме как i2c, так и i3c. А этот вопрос, в свою очередь, включает в себя описание порядка переключения шины из одного режима в другой и, соответственно, возможности отправки команд CCC устройствам i3c, находящимся в режиме i2c.
Для примера остановимся на группе команд, связанных с назначением адреса. Таких команд несколько: RSTDAA, ENTDAA, SETDASA, SETNEWDA, SETAASA. Некоторые из них могут быть как широковещательными, так и адресными. Конечно же, такие пары имеют разные коды и формат (например, с последующим байтом адреса и без него).
Самый простой способ назначить динамические адреса ведомым устройствам i3c — это заставить их использовать имеющиеся статические адреса в качестве динамических. Тем более, что это можно сделать всего одной широковещательной командой SETAASA, либо для конкретного устройства — командой SETDASA.
Если же необходимо самостоятельно распределить адреса на шине i3c, то процедура будет несколько сложнее.
Широковещательная команда ENTDAA заставляет все подчиненные устройства i3c (если они еще не имеют назначенного динамического адреса) перейти в режим назначения адреса. Далее, ведущее устройство отправляет повторный START и широковещательный адрес 0x7E с битом RnW, установленным в единицу. Каждое i3c устройство, еще не имеющее динамического адреса, должно подтвердить прием ACK-ом и в цикле отправить свой 48-ми битный, так называемый, «предварительный идентификатор» (Provisional ID). При этом задействуется процесс арбитража динамической адресации, при котором устройство с большим идентификатором выигрывает арбитраж, и ведущий отправляет ему его адрес. После чего устройство, получившее динамический адрес, перестает передавать свой «предварительный идентификатор» и выбывает из процесса. Следующее устройство выигрывает арбитраж и т. д. Процедура всегда заканчивается STOP.
Стоит отметить, что прежде, чем начать назначение динамических адресов, ведущее устройство должно знать, сколько у него подчиненных устройств на шине. Это может быть выполнено разными способами: опросом шины, получением количества устройств на шине от хоста (например, от драйвера ОС), считыванием значения из собственной памяти и т. д.
Еще одна команда управления адресацией — SETNEWDA. Позволяет сменить один назначенный динамический адрес на другой. Например, последовательность SETAASA, SETNEWDA позволяет избежать реализации процедуры, связанной с ENTDAA в простых системах, использующих i3c.
Команда RSTDAA сбрасывает назначенный одной из вышеперечисленных команд динамический адрес – либо для всех устройств сразу (широковещательный вариант RSTDAA), либо адресно, с указанием конкретного динамического адреса для сброса.
Мы рассмотрели самые общие случаи управления адресацией с использованием CCC команд. В реальности вариаций может быть больше, так как на шине могут присутствовать, например, такие устройства, как i3c-коммутатор (i3c hub) или i3c-мост (i3c bridge).
Прерывания IBI
Если вы еще не сталкивались с IBI, то в i3c используются так называемые «внутришинные» прерывания (inband interrupts), т. е. прерывания, не использующие дополнительные физические линии (пример – MSI, Message Signaled Interrupts – отправка прерываний сообщениями) в отличие от классических прерываний (outband), требующих отдельную линию и отдельный порт для реализации.
Чтобы запросить прерывание, ведомое устройство выжидает появления START (но не повторный START, чтобы не вклиниваться в текущий обмен) или генерирует собственную команду START, за которой отправляет свой адрес с битом RnW, установленным в 1. Ведущееустройство распознает это состояние и читает данные прерывания с вызвавшего прерывание устройства обычным чтением. Спецификация говорит только об одном байте данных сообщения прерывания, но нужно понимать, что, в общем случае, их может быть больше. Например, их количество может задаваться в одном из регистров устройства. Для устранения возможной конкуренции на шине ведущее устройство использует режим приоритетов, описание которого выходит за рамки данной статьи.
Прерывания IBI могут использоваться для сообщений об ошибках обмена данными, уведомлений о состоянии ведомого устройства или сигнализации о готовности данных. Спецификация никак не ограничивает прикладное применение прерываний.
Горячее подключение Hot-Join
Еще одна новая функция — это горячее подключение (hot-join) устройств на шину. Механизм горячего подключения описывает порядок действий всех участников на шине для определения и включения в обмен новых устройств. Этот механизм также обеспечивает возможность глубокого «засыпания» устройств i3c для экономии энергии с «просыпанием» и повторным подключением. Горячее подключение предъявляет дополнительные требования к устройствам на физическом уровне (например, порядок подтягивания к логической единице линий SCL/SDA и т. п.). На транспортном и сеансовом уровне задействуется механизм прерываний IBI и определяется собственная процедура обмена с использованием CCC команд.
Для прерываний IBI используется зарезервированный адрес 0x02 с установленным битом RnW. Подчиненное устройство, дождавшись момента, когда шина свободна, отправляет запрос на прерывание с указанным адресом (данная последовательность представляет собой запрос на назначение динамического адреса). Ведущее устройство отвечает командой ССС ENTDAA. Подключающееся ведомое устройство отправляет свой предварительный идентификатор, и далее процесс совпадает с процедурой назначения динамического адреса, описанной выше. Отдельно отмечено, что ведущее устройство должно назначать ведомым всегда один и тот же адрес.
У ведущего устройства нет никаких возможностей определить, отключилось ли ведомое или нет, кроме как периодически опрашивать шину. Сделать это оно может, например, проверяя состояние устройств CCC командой GETSTATUS.
Известные расширения I3C
I3c оставляет достаточно широкий простор для расширения. Многие компании активно готовят рецепты применения протокола для своих продуктов. Описание некоторых из них уже доступно в публичном доступе. Например, i3c используется в качестве транспорта для SMBus, при организации доступа к SPD (Serial Presence Detect — механизму используемому для идентификации и конфигурации модулей памяти), в обмен добавляется возможность позиционирования (задания адреса) — каждая операция чтения-записи предваряется записью в ведомое устройство требуемого адреса. Спецификация SMBus содержит детальное описание таких транзакций.
Выделение в протоколе i3c CCC команд, зависящих от конкретного поставщика (vendor specific) расширяет возможности протокола i3c вообще без вмешательства в основы. Например, если чтение или запись идут постоянно из одного адреса, то можно ввести для этого собственную команду и вести опрос, не тратя полосу на типовую предварительную преамбулу.
Что дальше?
С одной стороны, сейчас едва ли можно найти контроллер или устройство, поддерживающее i3c, поэтому при необходимости написать соответствующий драйвер или даже разработать аппаратуру того или иного датчика большим подспорьем будет использование симулятора. Например, Simics или ему подобного. В Simics разработка модели i3c контроллера займет около 3 недель. После чего она может быть использована для запуска немодифицированного бинарного драйвера, в том числе в составе BIOS, bootloader или OS.
С другой стороны, если вы занимаетесь разработкой прикладного ПО с использованием различных датчиков, стоит обратить внимание на новый фреймворк i3c для Linux (3).
И то, и другое позволит начать использование новейших решений уже сейчас.

Источники
- UM10204 I2C-bus specification and user manual Rev. 6 — 4 April 2014, User manual. Документ доступен по ссылке.
- MIPI Alliance, Specification for I3C Basic Improved Inter Integrated Circuit Version 1.0 – 19 July 2018, MIPI Board Adopted 8 October 2018. Документ доступен по ссылке после бесплатной регистрации.
- Материалы сайта “Embedded Linux Wiki” по ссылке.
- System Management Bus (SMBus) Specification Version 3.1 — 19 Mar 2018. Документ доступен по ссылке.