‮Сдвиг по фазе (kincajou) wrote,
‮Сдвиг по фазе
kincajou

Categories:

worklog: STM32F746 I2C через DMA. Забавный нюанс

Чем дальше я разбираюсь с тонкостями работы DMA в чипах STM32, тем бОльшее благоговение они у меня вызывают. Если и процессор, и каждый из периферийных модулей представляется мне эдакой коробочкой с контактами; то DMA это эдакое ... эдакий... короче, нечто типа профессора Мориарти или даже РЖД - глобальная система, протянувшая свои щупалки в каждую дырочку.

Щас вот нашёл интересное. Вот есть концепция "событие DMA". Это некий бит в некоем регистре - в каких-то периферийных модулях он логически совпадает с флагом какого-либо прерывания, в каких-то других он может и не иметь соответствующего прерывания. Когда бит устанавливается в 1, то это побуждает модуль DMA передвинуть очередную порцию данных. Если DMA не включен, но есть разрешённое прерывание, то вызовется его обработчик. А что будет, если одновременно включить и DMA, и прерывание?

А х.з. В каких-то случаях не сработает ни, то, ни другое. Но в других может сработать что-то одно из. Почему так - я не знаю.

Собсно, щас переделал процыдурку с циклов ожидания на прерывания. Сначала взводим прерывание от I2C, разрешая реакцию на флаги NACKF ("в ответ на наш байт получен NACK") и TXIS ("буфер передатчика пуст и готов к новым данным"). Т.е. алгоритм такой:
1) инициализируем
2) разрешаем прерывание
3) генерим START
4) ...
5) срабатывает прерывание I2C1_EV ("event"; для ошибок есть отдельный вектор I2C1_ER). В нём я смотрю, какой имеено флажок выставлен. Если NACK, то через глобальную переменную возвращается состояние ошибки. Если TXIS, то включается соответствующий поток DMA с его прерыванием.
6) ....
7) срабатывает прерывание DMA1_StreamX, тут уже смотрим на номер канала. Если это наш канал (для I2C1 это всегда номер 1), то после сбоса и отключения модуля DMA через ту же глобальную переменную возвращаем состояние успешной передачи.

Нюанс как раз в том, что TXIS это одновременно ещё и событие DMA, если про это забыть, то можно очень долго ждать срабатывания хоть чего-нибудь.

Теперь следующая итерация - заменить обмен данными через глобальную переменную на синхронизацию через семафоры или даже через очереди РТОС. Непонятно только, что будет с временем обработки - если цикл-крутилка на изменение переменной реагирует почти мгновенно, то у РТОС же есть какая-то гранулярность событий, быстрее чем за 1 тик она не реагирует.. или реагирует?
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 2 comments