Один и тот же IP-блок I2C кочует по миру. В I2C CH32V006, похоже,
такой же баг в аналоговом фильтре, какой был у STM32F1xx. Если на выводах I2C напряжение появляется
раньше, чем питание, модуль зависает в BUSY и переходит в BUSY
через пару мкс после сброса. Модуль I2C считает линию "BUSY", в то время когда на самом деле SCL и SDA - кристально-чисты и высоки. Причём, проявление зависит от обвязки МК и порядка инициализации периферии.
Как глаголит оригинальная Errata от STM, проблема проявляется случайно и может быть вызвана ЭМП.
И действительно, то работает, то не работает. Например, мастер иногда успевает запуститься за те пару микросекунд, пока "ощущение BUSY" "не дошло" после свежего сброса. И, после шевеления лапок на шине, приходит в норму и работает. Но иногда не успевает. Другой чип на плате стартует с I2C всегда. Зависит от обвязки МК и порядка инициализации периферии, порядка появления напряжений.
Например, имею на плате пару одинаковых МК CH32V006. Несколько одинаковых плат. И на них эта пара МК ведёт себя одинаково от платы к плате: один МК запускается от линейного стабилизатора чуть раньше, чем другой. И подтяжка I2C запитывается раньше, чем МК, питающийся от DC/DC. И МК, на который напряжение по шине пришло раньше питания, возможно, раньше включения тактирования I2C (по форумам, от порядка включения тактирования - зависит) - зависает со 100% вероятностью, если не включить передачу "старта" сразу после сброса, пока не обнаружено дефектное BUSY.
Неужели так трудно доработать ранее созданное? (это про IP-блок)
План такой:
- При старте, включаю тактирование I2C. Настраиваю GPIO как выходы порта с открытым коллектором (не как альтернативную функцию I2C);
- Делаю Software Reset I2C. Отпускаю сброс.
- Жду 4мкс+. Проверяю Busy не включая модуля (он работает без enable).
- Если BUSY - вывожу открытым коллектором, через GPIO, низкий уровень на оба входа. Жду 4мкс.
- Отпускаю открытый коллектор. Жду 4мкс. Делаю Software Reset.
- Жду 4мкс. Проверяю BUSY.
- Если не BUSY в первом или во втором тесте, переключаю GPIO в режим альтернативной функции - на I2C.
- Настраиваю модуль. Включаю. Работаю.
- Если при работе - таймаут - не разбираясь, делаю всё сначала.
По идее, так будет работать надёжно.