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

Как разбудить STM32L0 из Stop по адресу I2C?

Обновлено Редакция GAW

У STM32L0 ведомый I2C может ждать своего адреса во сне: пока на шине тишина, ядро в Stop, а при обращении к нему интерфейс сам включает генератор и будит микроконтроллер. Это удобно для датчиков и сопроцессоров, которые опрашивает главный контроллер.

Условия по RM0377

ЧтоЗначениеЗачем
ИнтерфейсI2C1 или I2C3у I2C2 нет пробуждения из Stop
RCC_CCIPR, I2CxSEL10 — HSI16от APB и системной частоты в Stop такта нет
I2C_CR1, WUPEN1разрешает пробуждение по адресу
I2C_CR1, DNF0с цифровым фильтром WUPEN не действует
I2C_CR1, NOSTRETCH0интерфейс растягивает SCL, пока ядро просыпается
ПрерываниеADDRIEбудит только ADDR

Как это происходит

  1. Ядро в Stop, HSI16 выключен.
  2. Ведущий выдаёт START — интерфейс включает HSI16 и держит SCL низким, пока генератор не запустится.
  3. Принимается адрес. Если он чужой, HSI16 снова выключается и ядро продолжает спать.
  4. Если адрес свой, ставится ADDR, ядро просыпается, а SCL остаётся растянутым, пока программа не сбросит ADDR, — дальше передача идёт как обычно.

Растягивание SCL — ключевая часть механизма, ведущий обязан его поддерживать (термин «Растягивание такта»). Цифровой фильтр помех придётся выключить; про аналоговый и цифровой фильтры — термин «Фильтр помех I2C». Если пробуждение по адресу не используется, RM0377 требует выключить интерфейс перед Stop битом PE.

Похожим образом устроено пробуждение по приёму у LPUART — оно разобрано в ответе «Почему LPUART не будит STM32L0 из Stop». Какие интерфейсы есть в каждой категории, показано на странице STM32L0.

Похожие вопросы

Не нарушит ли растягивание SCL работу ведущего?

Пока ведомый просыпается, он держит SCL низким, и ведущий должен это поддерживать. Если ведущий не умеет ждать на растянутом такте, пробуждение по адресу с ним не заработает. Как устроено растягивание, описано в термине «Растягивание такта».

Почему пробуждение не работает с включённым фильтром помех?

По RM0377 цифровой фильтр I2C несовместим с пробуждением из Stop: если DNF не равен нулю, бит WUPEN ничего не делает. Аналоговый фильтр при этом можно оставить, ограничение касается только цифрового.

Когда можно снова засыпать после пробуждения?

Не раньше конца транзакции. RM0377 советует в обработчике ADDR сбросить бит SLEEPDEEP и снова установить его только после флага STOPF, иначе ядро может уснуть посреди передачи, а будит его только новое совпадение адреса.

Источники

  1. STMicroelectronics. RM0377 Reference manual: Ultra-low-power STM32L0x1 advanced Arm-based 32-bit MCUs, Rev 10 — разд. 23.3, табл. 100: независимый такт и пробуждение из Stop есть у I2C1 и I2C3, у I2C2 нет; разд. 23.4.16: пробуждение по совпадению адреса при WUPEN = 1 и такте I2CCLK от HSI16; в Stop HSI16 выключен, по START интерфейс включает HSI16 и держит SCL низким, при совпадении адреса растягивает SCL на время пробуждения до сброса флага ADDR, при несовпадении HSI16 снова выключается; будит только прерывание ADDR; цифровой фильтр DNF ≠ 0 несовместим с пробуждением; требуется NOSTRETCH = 0; при WUPEN = 0 перед Stop выключают I2C (PE = 0); разд. 7.3.19: I2C1SEL — 00 APB, 01 системная частота, 10 HSI16; табл. 54: линии EXTI 23 (I2C1) и 24 (I2C3) — прямые
  2. STMicroelectronics. cmsis-device-l0, Include/stm32l053xx.h (commit 7b7ae8c) — I2C_CR1: DNF — биты 11:8, NOSTRETCH — бит 17, WUPEN — бит 18; RCC_CCIPR_I2C1SEL — биты 13:12, RCC_CCIPR_I2C1SEL_1 = 0x2000 (HSI16)

Нашли ошибку?