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

Лютый баг в DMA STM32F4: кто-нибудь в курсе?

32 минуты назад, jcxz сказал:

Неужто Ваша задача чем-то занята целых 80мсек...

Нет конечно, я предполагаю такой ситуации вообще никогда не возникнет.
Сейчас все на бумаге, но нужно сразу закладываться на нештатные режимы (а вдруг что?).
ТЗ на поведение при нештатных режимах - нет, полная свобода для творчества, но я хочу сделать максимально четко.

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


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

А кто как обрабатывает ошибки UART модуля при работе на прием через DMA? Т.е. при любой ошибке (framing error, например) что делаете? Сбрасываете весь FIFO? Грубо говоря, имея рабочий буфер в 8 кБ, помеха на линии технически заставит отбросить все уже имеющиеся корректные данные из этого буфера? Просто дело вот в чем: я же хотел попробовать поделить буфер на множество сегментов, и каждому сегменту отвести 1-битный флажок "валидности" данных. При возникновении ошибки текущий DMA-сегмент помечается как не валидный и при чтении данных из FIFO это будет учтено (просто нужно будет откинуть данные лишь одного сегмента, а не всего буфера). Только вот есть некая засада: нет средств аппаратного удержания номера активного DMA-буфера, в который прилетел "битый" символ. Программная реализация, ИМХО, надежно не реализуется, т.к. в любом случае пара прерываний TC от DMA и UART Errors образует гонки состояний, особенно при возникновении ошибок в конце текущего активного буфера и начале следующего заполняемого при сплошном высокоскоростном UART-потоке... Разве что помечать не валидными пару буферов (текущий и следующий) сразу.

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


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

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

А кто как обрабатывает ошибки UART модуля при работе на прием через DMA? Т.е. при любой ошибке (framing error, например) что делаете? Сбрасываете весь FIFO?

Всё зависит от назначения данного UART: с чем именно, в каких условиях работает и какой протокол обмена по нему ходит?

1. Например у меня, для UART-а, на котором сидит ESP8266, любое такое событие - абсолютно недопустимо, и при его возникновении: Останов драйвера ESP (со всеми вышележащими драйверами по иерархии) и реинит UART-а (с DMA). Так как такие события не могут происходить при нормальной работе (ESP8266 находится на той же плате где и МК, короткие линии связи); и потому что АТ-протокол обмена ESP8266 не устойчив к такого рода сбоям (правильное восстановление после такого сбоя в общем случае невозможно).

2. Если же на этом UART-е например RS-485, по которому к тому же ходит протокол, устойчивый к помехам на линии (кодонезависмый, с правильным фреймингом и контролем содержимого) и помехи на линии возможны исходя из самого характера работы системы: то можно и просто сбросить состояние ошибки, накопленные FIFO (все: аппаратные + программные), и сбросить машину состояний парсера протокола обмена.

 

Но даже в случае с RS-485, если (исходя из характера работы системы) допустимо пойти 1-м вариантом, но лучше так и сделать. Так как проще и надёжнее. Идти 2-м путём имеет смысл если выполняются все условия (2-го варианта) и есть реальная необходимость: канал плотно загружен обменом, или по нему ходят реалтайм-данные и необходимо как можно более быстрое восстановление связи после помех и т.п.

 

PS: Так что сначала нужно всё-таки определиться: реально оно нужно, или можно пойти по 1-му варианту? И если нужно, то зачем? Отсюда и танцевать. А смысла в универсальных конях в вакууме я не вижу.  :unknw:

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


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

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

Всё зависит от назначения данного UART: с чем именно, в каких условиях работает и какой протокол обмена по нему ходит?

А разве реализация драйвера FIFO должна учитывать протокол, который будет ходить поверх? Я думаю, что это не совсем корректно. ИМХО, достаточно, читая статус очереди при вычитке данных из нее функцией read(), каким-то образом сообщить клиентскому коду, что с данными (запрошенными) все в порядке. Сделать это можно как раз по принципу, похожему на механизм виндовых функций ReadFile(). Т.е. запрашиваем сколько-нибудь данных, а она считывает столько, сколько было реально получено без каких-либо коллизий (но не более запрошенного количества). Выше примерный псевдокод я уже приводил. Ну либо отдельной переменной (ссылкой, по указателю - как угодно) передавать, а после проверять что там - если была лажа в потоке, сбрасываем автоматы протоколов выше. ИМХО, такое FIFO подойдёт и под ESP: просто увидев коллизию в очереди, вызываем функцию очистки ее и все.

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


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

37 минут назад, Arlleex сказал:

ИМХО, такое FIFO подойдёт и под ESP: просто увидев коллизию в очереди, вызываем функцию очистки ее и все.

И что? А дальше как работать? Ну очистили вы FIFO, а как теперь данные получать из потока? Ещё раз: у ESP АТ-командный протокол не кодонезависимый! Поэтому если взять и просто выбросить кусок потока байт, то далее уже невозможно определить, что идёт после этого пропуска: часть команды или часть блока данных или ещё чего. 

Я имею в виду именно АТ-командный протокол работы ESP8266.

То же самое касается и любых других некодонезависимых протоколов: не поможет там очистка FIFO, никак.

 

PS: А если протокол кодонезависимый и очистка имеет смысл, то в ISR обработчика ошибок можно посмотреть текущий объём данных в приёмном FIFO, и послать сигнал RX-парсеру; парсер получив этот сигнал должен просто скипнуть указанный объём и всё. Это самый простой способ имхо. И тогда можно обойтись простой реализацией FIFO: с одним читателем одним писателем (без лищних блокировок на критических секциях). Никаких очисток в обработчике ошибок делать не надо.

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


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

Заметил в связке DMA + UART (передача "память -> периферия") на довольно бодрых скоростях (921600 и выше до предельных возможностей UART-модуля), что устанавливается флаг ошибки FIFO DMA-потока. Хотя у меня выбран Direct Mode (DMDIS = 0). На маленьких скоростях UART-а не проверял (ибо отлаживался сразу на мегабите). DMDIS = 1 и любые вариации FIFO Level Treshold проблему не решают. При этом, собственно, данные все передаются верно (нет "перезаписанных" или вовсе отсутствующих байтов в потоке). Читая RM, пока что пришел к выводу, что (согласно описанию бита FIFO Error Interrupt Flag - FEIF) DMA не успевает "подгрузить" данные из памяти во внутренний FIFO и происходит т.н. Underrun Condition. Ведь DMA опирается на флаг TXE UART-модуля, который взводится практически сразу после записи в пустой DR (когда DR "сливается" в непосредственный сдвиговый регистр).

Даже не понятно теперь, как обрабатывать FEIF, по-хорошему. Либо запретить вовсе это прерывание.

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


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

5 часов назад, Arlleex сказал:

Даже не понятно теперь, как обрабатывать FEIF, по-хорошему. Либо запретить вовсе это прерывание.

Так он у вас возникает наверное из-за direct mode. А зачем UART-у direct mode? Если не секрет.

Да и какая разница - есть этот FEIF или нет, если не используете Modbus или что-то подобное? UART - это ведь асинхронный интерфейс, а не синхронный.

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


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

10 часов назад, jcxz сказал:

Так он у вас возникает наверное из-за direct mode. А зачем UART-у direct mode? Если не секрет.

На прием нужен Direct Mode. На передачу, собственно, тоже, т.к. FIFO Mode (DMDIS = 1) полезен, когда ширины шин памяти и периферии различны или когда используются Burst-транзакции. У меня же DMA-поток направляет массив байтов из ОЗУ в UART->DR, соответственно, MSIZE = PSIZE = 8 (бит), MBURST = PBURST = Single Transfers.

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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