Перейти к содержанию
    

STM32F4. Завершение I2C-транзакции.

Просматривая один свой проектик на STM32F4, обратил внимание, что при завершении I2C-транзакции (I2C-мастер) выставляю СТОП-условие на шину и после этого жду полного завершения активности на шине поллингом бита MSL в I2C_SR2. Хотя все остальные действия работают по прерываниям. Проверил и точно: после выставления СТОП-условия (I2C_CR1.бит9) я уже больше не получаю никаких прерываний от I2C-периферии. В то время как сам бит MSL обнуляется естественно не сразу после подачи СТОП.

Получается, что без поллинга тут не обойтись? Или я где-то чего-то проглядел и как-то можно заставить I2C-периферию сгенерить прерывание при окончательном освобождении шины?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А перед началом обмена с I2C нельзя проверять этот бит и ждать если надо ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, x893 сказал:

А перед началом обмена с I2C нельзя проверять этот бит и ждать если надо ?

Ну а какая разница - поллинг в начале или в конце? Желательно вообще без поллинга.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В свое время тоже пытался сделать обмен чисто на прерываниях, только окончание прошлой транзакции я оценивал по биту BUSY.

Сейчас глянул в исходник - все на прерываниях, кроме злосчастного поллинга BUSY перед началом передачи. Западло, однако...

 

P.S. Интересно снять осциллограмму в случае, когда выставляется STOP и сразу же осуществляется попытка передать START - возможно, контроллер I2C корректно обработает эту портянку и надобность в поллинге отпадет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Arlleex сказал:

В свое время тоже пытался сделать обмен чисто на прерываниях, только окончание прошлой транзакции я оценивал по биту BUSY.

Сейчас глянул в исходник - все на прерываниях, кроме злосчастного поллинга BUSY перед началом передачи. Западло, однако...

Получается - так и не смогли STM-щики сделать нормальный I2C? А вроде кто-то говорил, что в старших STM он уже нормальный.... :sad:

Прям какая-то засада с ним! Купили бы что-ли у других производителей. Другие с первого раза нормальный делают как-то.... :wacko2:

Цитата

P.S. Интересно снять осциллограмму в случае, когда выставляется STOP и сразу же осуществляется попытка передать START - возможно, контроллер I2C корректно обработает эту портянку и надобность в поллинге отпадет.

Старт-стоп работает. По-крайней мере если ставить оба бита СТАРТ и СТОП одновременно. Иначе бы вообще нельзя было работать с некоторыми слэйвами, которые переключаются на приём именно такой последовательностью.

Но если что делать если следующая транзакция должна быть с другим слэйвом? Писать новый адрес пока на закончилась предыдущая транзакция думаю нельзя. У меня на шине много разных устройства.

И что делать если не нужно делать повторный старт? А нужно просто узнать что транзакция закончилась. Например - чтобы отключить после этого периферию. Ну или ещё что-то сделать.

 

PS: Похоже - если полностью корректно делать, то нужно задействовать дополнительный таймер. Ситуация блин прям как с нахождением стоп-бита UART.  :sad:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, jcxz сказал:

Получается - так и не смогли STM-щики сделать нормальный I2C? А вроде кто-то говорил, что в старших STM он уже нормальный.... :sad:

STM нормально никогда не делали особо. Они сделали в старших сериях чуть получше, ИМХО, но не идеально.

 

1 час назад, jcxz сказал:

И что делать если не нужно делать повторный старт? А нужно просто узнать что транзакция закончилась...

Собственно, только поллить.

 

1 час назад, jcxz сказал:

PS: Похоже - если полностью корректно делать, то нужно задействовать дополнительный таймер...

Я делал и на прерываниях, и на прерываниях + DMA. Года четыре назад, когда первый раз писал драйвер I2C под STM32F4, нахлебался косяков в работе этого поделия, в том числе таких, при которых модуль повисал намертво до полной перезагрузки его через RCC-регистры. И никакие серии стоп- или -старт-бит не помогали, только сброс через RCC и полный реконфиг. А не так давно снова пришлось поддерживать I2C под этот камень, но тут я сделал немного по-другому: транзакции и управление состоянием автомата I2C по-прежнему в прерываниях, транзакции данными по DMA, но вся посылка (или некоторые ее части) обрамляется таймерным сторожем. На картинке пример.

 

image.png.841c5daa0bc1f6ac046ed91f43460933.png

 

Так начинается транзакция. В момент (1) происходит запрос на формирование START-условия. Дальше, если тупо поллить, в программе будет бесконечный цикл ожидания установки флага, сигнализирующего о том, что условие сформировано на шине (но я не поллю). А если по прерываниям делать, то поллить не надо и мы влетаем (2) через какое-то время в обработчик, и делаем следующий шаг (3) в алгоритме I2C-автомата - отправляем аппаратный адрес микросхемы.

Ну дык вот. Таймер у меня в момент (1) заряжается на интервал, который чутка больше по времени между событиями (1) и (2). Формирую START и запускаю таймер. В ISR I2C, как только обнаружил START-ack (бит SB регистровой модели I2C STM32F4), таймер останавливаю. Теперь надо отправить адрес микросхемы, но до этого рассчитываю интервал таймера на чуть больше времени передачи одного байта; отправляю адрес и запускаю таймер. И так по всему циклу автомата. Если хоть где-то выстрелит прерывание по таймеру, это будет значить, что произошла какая-то лажа на шине - в этом случае я сбрасываю транзакцию, уведомляю необходимые потоки RTOS об этом и перезапускаю периферию.

 

1 час назад, jcxz сказал:

Ситуация блин прям как с нахождением стоп-бита UART...

А там что?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 hours ago, jcxz said:

Ну а какая разница - поллинг в начале или в конце? Желательно вообще без поллинга.

Разница огромная. После инициализации STOP можно делать что-то полезное, а не ждать окончания STOP.

А когда надо передавать новые данные, тогда и потратить (если STOP еще не закончился) время на ожидание.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 часа назад, Arlleex сказал:

Я делал и на прерываниях, и на прерываниях + DMA. Года четыре назад, когда первый раз писал драйвер I2C под STM32F4, нахлебался косяков в работе этого поделия, в том числе таких, при которых модуль повисал намертво до полной перезагрузки его через RCC-регистры. И никакие серии стоп- или -старт-бит не помогали, только сброс через RCC и полный реконфиг. А не так давно снова пришлось поддерживать I2C под этот камень, но тут я сделал немного по-другому: транзакции и управление состоянием автомата I2C по-прежнему в прерываниях, транзакции данными по DMA, но вся посылка (или некоторые ее части) обрамляется таймерным сторожем.

У меня этот драйвер работает примерно 1.5 года - проблем вроде не замечал особых. На этой шине висят: FRAM+RTC+тач_пад+тюнер. Всё работает стабильно. Правда я не совсем честно сделал SCLK - он у меня push-pull. Если сделать его OK - очень редко происходят сбои (видимо проводов и их ёмкости слишком много). Никаких таймаутов не отслеживаю - по любой ошибке (или не-ACK) у меня должно сразу падать в ловушку критической ошибки и защёлкиваться в этом состоянии. Но этого не происходит - проверено за это время многими днями непрерывной работы.

Работаю по прерываниям + DMA. Планировщик транзакций автоматически определяет необходимость DMA (по размеру пересылаемых данных). Единственное место которое вызывает недовольство - это указанное в заголовке темы. Похоже потрачу один таймер и сделаю поллинг в этом месте по его прерываниям.

 

PS: Хотя конечно I2C в STM32F4 не выдерживает никакого сравнения с I2C в XMC47xx. Вот там сделано действительно отлично! Умеют немцы  :ok:

Там не нужно всех этих прерываний, и возни с битами-флагами в них. Можно сразу всю транзакцию записать в виде единой посылки, кодирующей все старты-стопы-рестарты-данные. И зарядить её через DMA в I2C. И получить одно прерывание в конце всей работы :ok:

2 часа назад, x893 сказал:

Разница огромная. После инициализации STOP можно делать что-то полезное, а не ждать окончания STOP.

А когда надо передавать новые данные, тогда и потратить (если STOP еще не закончился) время на ожидание.

Разницы нет никакой в том плане, что всё равно нужно ждать. Хоть где. Понятно что можно на хромой козе объехать. Но блин - умеют же другие вендоры делать без коз!

И ожидание у меня в конце, потому что я стараюсь так строить драйверы периферии: включил периферию, поработал с ней, если нет другой работы для неё - выключил.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 часа назад, Arlleex сказал:

А там что?

Ну в STM32F4 этой проблемы нет. Это было в других МК. LPC17xx например. Там не было прерывания завершения передачи символа по UART. И например для RS-485, где нужно переключать направление передачи в линии, приходилось делать поллинг регистра статуса на прерываниях таймера.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

13 hours ago, jcxz said:

И ожидание у меня в конце, потому что я стараюсь так строить драйверы периферии: включил периферию, поработал с ней, если нет другой работы для неё - выключил.

Не совсем понимаю, а зачем выключать периферию, если она после текущей транзакции пока не нужна? Почему бы её просто не оставить включенной?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 минут назад, haker_fox сказал:

Не совсем понимаю, а зачем выключать периферию, если она после текущей транзакции пока не нужна? Почему бы её просто не оставить включенной?

Привычка, оставшаяся с моих проектов с батарейным питанием  :wink2:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...