Почему шина I2C зависает после перезагрузки микроконтроллера?
Обновлено Редакция GAW
Ведущий и ведомый на шине I2C не имеют общего сигнала сброса. Если микроконтроллер перезагрузился посреди транзакции — от сторожевого таймера, кнопки или просадки питания, — датчик об этом не узнает. Он остаётся в том месте байта, где его застал сброс.
Как это происходит
- Микроконтроллер читает данные, датчик выставляет на SDA очередной бит — 0.
- В этот момент микроконтроллер перезагружается и перестаёт выдавать такты SCL.
- Датчик ждёт следующего такта и держит SDA в нуле сколько угодно.
- После старта контроллер I2C видит SDA в нуле, считает шину занятой и не может сформировать START.
Снаружи это выглядит так: до перезагрузки всё работало, после — датчик «пропал», и помогает только выключение питания.
Что делать
По UM10204 действия зависят от того, какая линия застряла:
| Линия в нуле | Что делать по UM10204 |
|---|---|
| SDA | ведущий выдаёт до девяти тактов SCL, датчик отпускает линию, затем STOP |
| SCL | аппаратный сброс устройств или снятие питания для внутреннего сброса по включению |
Девять тактов — это восемь бит байта и бит подтверждения: за это время любой прерванный байт заканчивается. Наш расчёт: на 100 кГц это 90 мкс, поэтому очистку шины ставят в начало программы всегда, перед инициализацией I2C, — вреда от неё нет.
Если SCL держит медленное устройство, это может быть и законное растягивание такта — тогда ждут, а не сбрасывают. Как убедиться, что линии свободны, рассказано в ответе «Как проверить шину I2C», последовательность битов транзакции показывает калькулятор «Транзакция I²C по байтам». Устройство шины — в статье «Шина I²C».
Похожие вопросы
Почему шина зависает не после каждой перезагрузки?
Зависание бывает, только если сброс пришёлся на момент, когда датчик сам передаёт бит 0 или подтверждение. Если в этот момент линию держал ведущий или передача уже закончилась, датчик ничего не ждёт. Поэтому ошибка выглядит случайной и чаще всплывает после срабатываний сторожевого таймера.
Поможет ли перезагрузить только микроконтроллер ещё раз?
Нет, если программа при старте не очищает шину: датчик продолжает держать SDA. Помогают девять тактов SCL перед инициализацией I2C или выключение питания самого датчика — UM10204 предлагает именно эти два пути.
Как сбросить шину, если датчик стоит за коммутатором TCA9548A?
У TCA9548A есть вход RESET: низкий уровень сбрасывает коммутатор и отключает все каналы, и зависший канал перестаёт блокировать основную шину. После этого канал можно выбрать снова и выдать в нём девять тактов.
Источники
- NXP. UM10204 I2C-bus specification and user manual (Rev. 7.0, 1 October 2021) — разд. Bus clear (3.1.16 в тексте): если SCL застряла в нуле, сбрасывают устройства аппаратным сигналом сброса, а без него — выключением питания, чтобы сработал обязательный внутренний сброс; если в нуле SDA, ведущий выдаёт девять тактов, и устройство должно отпустить линию, иначе — аппаратный сброс или питание; разд. 3.1.14 — программный сброс через общий вызов (необязательная функция, есть не у всех устройств)
- Texas Instruments. TCA9548A Low-Voltage 8-Channel I2C Switch with Reset (SCPS207H, revised September 2024) — вход RESET с активным низким уровнем — сброс и отключение всех каналов без снятия питания, чтобы восстановиться, если нижняя шина застряла в нуле; длительность импульса RESET не меньше 6 нс
Нашли ошибку?
Смотрите также
- Сброс зависшей шины I²CВосстановление шины I²C тактами SCL, когда ведомый удерживает SDA в нуле
- Растягивание такта I²CВедомое держит SCL в нуле: зачем, ограничения SMBus, совместимость
- Как проверить шину I2C?Уровни SDA и SCL в покое, сканер адресов и девять тактов
- I²CSDA и SCL, START/STOP, ACK, адреса, скорости, расчёт подтяжек
- Транзакция I²C по байтамБайт адреса, ACK и NACK, повторный START, диаграмма и код