Rockchip · AI & Linux Hub

Аппаратные интерфейсы

Rockchip I2C: алгоритмы контроллера, временные параметры, DTS и диагностика NACK/тайм-аутов

Полная настройка i2c-rk3x/i2c-rockchip, I2C tools, GPIO I2C и подробный анализ неисправностей шины.

· ArmSoM Editorial · Rockchip source documentation · 13 мин чтения

Применимость к ArmSoM и область исходника

Справочный материал для адаптации ArmSoM на основе CN/EN V2.2.0. Сочетания платы, SDK/BSP, ядра и соединений аппаратно не проверялись. Область исходника ниже не означает поддержку каждой платой ArmSoM либо каждым ядром. Проверьте SoC, схему, SDK/BSP, драйвер и pinmux. Команды, патчи, журналы и измерения взяты из исходника и не являются тестами ArmSoM.

Рисунки китайской версии взяты из китайского PDF, английской и русской — из английского.

SoC исходника Ядра по исходнику
All chips All version

I2C Rockchip передаёт данные по SDA и SCL. Каждое устройство имеет уникальный адрес и может передавать либо принимать данные: MCU, LCD, память, клавиатурный интерфейс. Поддерживаются I2C/SMBus, только режим ведущего, программируемая частота до 400kbps (для части SoC 1000kbps), адресация 7/10 бит и до 32 байт за прерывание либо опрос. Нужны подтягивающие резисторы, их номинал задаёт силу подтяжки. В зависимости от SoC и ядра используется i2c-rk3x.c либо i2c-rockchip.c, последний — в ядре 3.10. Исходник указывает типовой максимум 1000K; проверьте SoC и электрические временные параметры.

Редакционные примечания · ArmSoM documentation · Rockchip Linux

Подключение подтяжки SDA/SCL I2C — источник EN PDF p.2

Подключение подтяжки SDA/SCL I2C — источник EN PDF p.2.

1. Последовательность работы I2C

Последовательность работы I2C в обоих драйверах для ядер 4.4 и 3.10 в целом одинакова: запись использует режим TX (I2C_CON[1:0] = 2'b00), чтение обычно использует TRX (I2C_CON[1:0] = 2'b01). Приведённые ниже блок-схемы показывают настройку и выполнение задач через регистры контроллера I2C: передачу, смешанный режим и приём.

1.1 Только передача (I2C_CON[1:0]=2’b00)

Алгоритм I2C только передачи — источник EN PDF p.6

Алгоритм I2C только передачи — источник EN PDF p.6.

1.2 Смешанный режим (I2C_CON[1:0]=2’b01 или I2C_CON[1:0]=2’b11)

Алгоритм смешанного режима I2C — источник EN PDF p.7

Алгоритм смешанного режима I2C — источник EN PDF p.7.

1.3 Только приём (I2C_CON[1:0]=2’b10)

Алгоритм I2C только приёма — источник EN PDF p.8

Алгоритм I2C только приёма — источник EN PDF p.8.

Выше показана основная последовательность работы I2C; подробности реализации смотрите в коде драйвера.

2. Настройка параметров драйвера I2C

Основной параметр — частота I2C. Допустимая частота зависит не только от SoC, но и от времени нарастания SCL/SDA: стандарт I2C ограничивает время нарастания и спада, особенно нарастания. Превышение максимального значения может привести к отказу обмена. Ниже приведены минимальные и максимальные значения из протокола и их взаимосвязь:

Частота I2C и пределы фронтов — источник EN PDF p.9

Частота I2C и пределы фронтов — источник EN PDF p.9.

Symbol Параметр Standard min Standard max Fast min Fast max Fast Plus min Fast Plus max Unit
fSCL Частота SCL   100   400   1000 KHZ
Tr Нарастание SDA/SCL   1000 20 300   120 ns
Tf Спад SDA/SCL   300 20×(VDD/5.5V 300 20×(VDD/5.5V 300 ns

В изображении нет закрывающих скобок формул минимального Tf; запись сохранена. Пустые ячейки не означают ноль.

Время нарастания Tr и спада Tf необходимо измерить осциллографом, как показано ниже:

Измерение фронтов I2C осциллографом — источник EN PDF p.9

Измерение фронтов I2C осциллографом — источник EN PDF p.9.

Настройка драйверов i2c-rk3x.c и i2c-rockchip.c различается.

2.1 Настройка i2c-rk3x.c

Параметры i2c-rk3x.c задаются в DTS; описание находится в Documentation/devicetree/bindings/i2c/i2c-rk3x.txt. Особое внимание — свойствам i2c-scl-rising-time-ns и i2c-scl-falling-time-ns:

clock-frequency: по умолчанию 100k, поэтому эту частоту можно не указывать. Для других частот требуется настройка. Максимально допустимая частота определяется i2c-scl-rising-time-ns. Например, для 400k задайте в DTS clock-frequency = <400000>;.

i2c-scl-rising-time-ns: время нарастания SCL определяется аппаратурой и регулируется подтягивающим резистором. Его нужно измерить осциллографом по схеме выше. Например, при 265 ns задайте i2c-scl-rising-time-ns = <265>;. Можно оставить значение по умолчанию, только убедившись, что фактическое время нарастания не превышает предел стандарта I2C для выбранной частоты.

i2c-scl-falling-time-ns: время спада SCL обычно почти не меняется и эквивалентно i2c-sda-falling-time-ns; как правило, значение по умолчанию менять не нужно.

&i2c1 {
    status = "okay";
    i2c-scl-rising-time-ns = <265>;
    i2c-scl-falling-time-ns = <11>;
    clock-frequency = <400000>;
    es8316: es8316@10 {
        #sound-dai-cells = <0>;
        compatible = "everest,es8316";
        reg = <0x10>;
        clocks = <&cru SCLK_I2S_8CH_OUT>;
        clock-names = "mclk";
        spk-con-gpio = <&gpio0 11 GPIO_ACTIVE_HIGH>;
        hp-det-gpio = <&gpio4 28 GPIO_ACTIVE_LOW>;
    };
};

2.2 Настройка i2c-rockchip.c

Для i2c-rockchip.c сохраняется зависимость допустимой частоты I2C от времени нарастания SCL: возможность увеличить частоту определяется i2c-scl-rising-time-ns. Сама частота задаётся непосредственно полем scl_rate структуры i2c_msg. По умолчанию это также 100k. Пример настройки 200K:

struct i2c_msg xfer_msg;
xfer_msg[0].addr = client->addr;
xfer_msg[0].len = num;
xfer_msg[0].flags = client->flags;
xfer_msg[0].buf = buf;
xfer_msg[0].scl_rate = 200 * 1000; /* 200K i2c clock frequency */

3. Использование I2C

Дополнительные инструкции находятся в Documentation/i2c/*. Далее рассматриваются интерфейсы чтения и записи.

3.1 Пространство ядра

Передача и приём Rockchip I2C используют стандартные интерфейсы Linux. Описание работы с клиентскими устройствами находится в Documentation/i2c/writing-clients исходного дерева ядра.

3.2 Пространство пользователя

Обычно устройства I2C управляются драйвером ядра, но к любому устройству на шине можно обращаться из пользовательского пространства через /dev/i2c-%d. Описание и примеры находятся в Documentation/i2c/dev-interface.

4. Утилиты I2C

I2C tools — открытый набор утилит, который можно загрузить и собрать кросс-компилятором: https://www.kernel.org/pub/software/utils/i2c-tools/. Исходная команда клонирования: git clone git://git.kernel.org/pub/scm/utils/i2c-tools/i2c-tools.git.

После сборки доступны i2cdetect, i2cdump, i2cset, i2cget и i2ctransfer, запускаемые из командной строки. Подробности сборки и использования смотрите в README и справке самих открытых утилит.

Дополнение из китайского PDF, стр. 11: i2cdetect перечисляет шины и сканирует устройства; i2cdump читает все регистры устройства; i2cget читает один регистр; i2cset записывает регистр.

5. Программная реализация I2C через GPIO

В ядре уже реализована эмуляция I2C через GPIO; описание находится в Documentation/devicetree/bindings/i2c/i2c-gpio.txt.

Пример узла I2C в DTS:

i2c@4 {
        compatible = "i2c-gpio";
        gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>, /* sda */
                <&gpio5 8 GPIO_ACTIVE_HIGH>; /* scl */
        i2c-gpio,delay-us = <2>; /* ~100 kHz */
        #address-cells = <1>;
        #size-cells = <0>;
        pinctrl-names = "default";
        pinctrl-0 = <&i2c4_gpio>;
        status = "okay";
        gt9xx: gt9xx@14 {
                compatible = "goodix,gt9xx";
                reg = <0x14>;
                touch-gpio = <&gpio5 11 IRQ_TYPE_LEVEL_LOW>;
                reset-gpio = <&gpio5 10 GPIO_ACTIVE_HIGH>;
                max-x = <1200>;
                max-y = <1900>;
                tp-size = <911>;
                tp-supply = <&vcc_tp>;
                status = "okay";
        };
};

Этот способ обычно не рекомендуется из-за низкой эффективности.

6. Частые вопросы по I2C

Поскольку используются два драйвера I2C, этот раздел также разделён на две части.

6.1 Драйвер i2c-rk3x.c

6.1.1 Ошибка NACK

Код возврата -6 (-ENXIO) интерфейса передачи I2C означает NACK: ведомое устройство не ответило. Причина обычно связана с периферийным устройством. Типичные случаи:

Неверный адрес I2C.

Неправильное состояние ведомого устройства: питание не включено, нарушена последовательность включения либо устройство неисправно.

Временная последовательность I2C не соответствует требованиям ведомого. Например, если вместо требуемого stop приходит repeat start, устройство может выдать NACK.

Внешние сигналы нарушают работу шины I2C; это можно обнаружить осциллографом.

6.1.2 Тайм-аут

6.1.2.1 Случай 1

Сообщение timeout, ipd: 0x00, state: 1 означает, что контроллер I2C работает некорректно, не формирует состояние прерывания и не может отправить start. Возможные причины:

Неверный IO-MUX выводов SCL или SDA.

Неверное напряжение подтяжки: оно недостаточно либо питание подтяжки отсутствует.

Периферийное устройство удерживает вывод I2C, из-за чего напряжение неверно.

Тактовый сигнал I2C не включён либо его частота слишком мала.

Одновременно установлены биты CON_START и CON_STOP.

6.1.2.2 Случай 2

Сообщение timeout, ipd: 0x10, state: 1 означает, что контроллер работает нормально, но CPU не обрабатывает прерывание I2C. Может быть заблокирован cpu0, на котором обычно обрабатывается это прерывание. Исходник предлагает cat /proc/interrups — написание пути сохранено как исходная ошибка и требует проверки. Другой вариант: источник прерывания I2C выключен и IRQ не запускает обработку CPU.

6.1.2.3 Случай 3

При timeout, ipd: 0x80, state: 1 значение ipd 0x80 означает, что SCL удерживается ведомым устройством. Если ведомых несколько, нужно определить какое именно:

Первый способ — поочерёдное исключение устройств. Он удобен, если периферийных устройств мало, а неисправность часто повторяется.

Второй способ требует изменения схемы: включите резистор последовательно в SCL и по падению напряжения определите, на какой стороне находится устройство, удерживающее низкий уровень. Резистор не должен нарушать обмен, но должен создавать измеримую разность напряжений; исходник предлагает около 1/20 сопротивления подтяжки или больше. Падение наблюдается и когда линию удерживает ведущий. Ещё нагляднее сравнить осциллограммы низкого уровня каждого ведомого и ведущего: устройство, чьё напряжение совпадает с уровнем при неисправности, удерживает шину.

Чаще удерживается SDA. Для определения виновного устройства используйте тот же подход, что и для SCL.

6.2 Драйвер i2c-rockchip.c

6.2.1 Ошибка NACK

Возврат -11 (-EAGAIN) интерфейса передачи означает NACK — другое устройство не отвечает. Обычно причина на стороне ведомого. Типичные случаи:

Неверный адрес I2C.

Неправильное состояние ведомого: нет питания, нарушена последовательность включения или устройство неисправно.

Временная последовательность не соответствует требованиям ведомого, например repeat start вместо требуемого stop приводит к NACK.

Внешние сигналы вызывают нарушение работы шины; это видно на осциллограмме.

6.2.2 Тайм-аут

6.2.2.1 Случай 1

При timeout, ipd: 0x00, state: 1 контроллер работает некорректно, не формирует состояние прерывания и не может отправить start. Возможные причины:

Неверный IO-MUX выводов SCL или SDA.

Напряжение подтяжки недостаточно или питание подтяжки отсутствует.

Периферийная схема удерживает вывод I2C, напряжение неверно.

Тактовый сигнал I2C выключен либо его частота слишком мала.

Одновременно установлены CON_START и CON_STOP.

6.2.2.2 Случай 2

При timeout, ipd: 0x10, state: 1 контроллер работает нормально, но CPU не обрабатывает прерывание I2C. Возможно, заблокирован cpu0, на котором обычно находится IRQ I2C; исходная команда — cat /proc/interrups (ошибочное имя пути отмечено в примечаниях). Также источник прерывания может быть выключен, поэтому IRQ не запускает обработчик CPU.

6.2.2.3 Случай 3

Сообщение timeout, ipd: 0x80, state: 1 либо scl was hold by slave означает, что SCL удерживается ведомым. При нескольких устройствах необходимо определить виновное:

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

Второй способ: добавьте последовательный резистор в SCL и по падению напряжения определите сторону устройства, удерживающего низкий уровень. Он не должен мешать передаче, но должен обеспечивать измеримую разность; обычно выбирают 1/20 сопротивления подтяжки или больше. Падение возникает и при удержании линии ведущим. Сравните осциллограммы низких уровней разных ведомых и ведущего с напряжением во время сбоя: совпадение укажет устройство, удерживающее шину.

Для более частого случая удержания SDA применяется та же методика, что и для SCL.

Сообщение i2c is not in idle (state =x) означает низкий уровень хотя бы на одной линии. Используйте описанную выше методику:

state=1: SDA находится в низком уровне.

state=2: SCL находится в низком уровне.

state=3: SCL и SDA находятся в низком уровне.

6.3 Анализ осциллограмм I2C

Если проблема не описана выше, лучший способ — захватить осциллограмму в момент ошибки и проанализировать обмен. Так можно определить большинство неисправностей I2C. При возникновении ошибки можно остановить текущую задачу I2C, например while(1), чтобы захваченный сигнал соответствовал сбою. При необходимости добавьте условие фильтрации, например адрес устройства I2C.

Другие статьи по теме → · Учебные маршруты →