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

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

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

Ещё раз: прерывание IDLE; задержка входа в ISR (из-за других ISR или запретов прерываний); за время задержки начался приём нового символа; вход в ISR (приём нового символа ещё не закончен - как раз принимается его стоп-бит); .

И стотыщпятьсот других более приоритетных прерываний. Какой длины должно быть FIFO, чтобы все всегда успевало?

 

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

Так поделитесь им с нами, вашим, правильным решением!

Нет, куда уж мне - молотить прерывания таймера с частотой приема символов и проверять в них NDTR - что может быть элегантнее?

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


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

Кстати, Сергей, а ведь можно и не выключать DMA по IDLE. Я хоть и разделяю точку зрения jcxz насчет нежелательного выключения DMA-канала, но ведь в этом IDLE вполне законно можно двигать указатель записи кольцевого буфера ровно так же, как это делается в прерывании по завершению всей транзакции. Т.е. DMA (как писали выше) настроить на непрерывный режим с двойным буфером и пусть себе молотит. Итого: завести буфер на 8 кБ, разбить его на 8 частей по 1 кБ, в прерываниях transfer complete DMA двигать указатель записи FIFO, основываясь на NDTR и назначать новые кусочки буферов для DMA. А в прерывании IDLE UART делать почти то же самое (двигать указатель записи, но не перепрограммировать DMA).

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


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

45 минут назад, Сергей Борщ сказал:

Нет, куда уж мне - молотить прерывания таймера с частотой приема символов и проверять в них NDTR - что может быть элегантнее?

Может не будем передёргивать? Arlleex говорил об 1кГц- прерывании. Я тоже говорил о примерно той же частоте. А "прерывания таймера с частотой приема символов" - это уже Вы сами придумали.

 

PS: И кстати Ваш метод (с прерыванием по IDLE) потенциально гораздо более ресурсоёмкий по производительности CPU. Т.е. - в худшем случае он нагрузит CPU гораздо сильнее, чем метод с периодическим прерыванием. Именно поэтому я и предпочёл сделать на периодическом прерывании, как у Arlleex.

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


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

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

Кстати, Сергей, а ведь можно и не выключать DMA по IDLE

Можно. Я уже не помню, почему так сделал.

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

PS: И кстати Ваш метод (с прерыванием по IDLE) потенциально гораздо более ресурсоёмкий по производительности CPU

Можно подробнее? Чем одно прерывание в конце посылки гораздо более ресурсоемко, чем периодическое? Если предположить, что нужна каждая посылка (т.е. на каждую посылку передающей стороной ожидается ответ), а не их пачка?

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


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

25 минут назад, Сергей Борщ сказал:

Можно подробнее? Чем одно прерывание в конце посылки гораздо более ресурсоемко, чем периодическое? Если предположить, что нужна каждая посылка (т.е. на каждую посылку передающей стороной ожидается ответ), а не их пачка?

Если предположить, что по UART у нас ходит не modbus (не надо отлавливать паузы), а какой-то другой протокол, в котором короткие паузы не означают ровным счётом ничего. И не нужна прям мгновенная реакция на завершение кадра (задержка в пару мс вполне допустима). То можно представить ситуацию, что на вход UART.RX поток символов поступает не тесно (старт-бит сразу за стопом предыдущего), а с паузами между символами чуть больше IDLE-time. Тогда будут получаться IDLE-прерывания с периодом = Tсимвола+IDLE-time. Сколько IDLE-time составляет в STM32F4? Предположим = 1.5 символа. Тогда, скажем на моём UART с 1843200 бод, я получу прерывания с частотой 184320/2.5 = 74кГц! Нехило так! Вместо 1 кГц. :shok:

Да и работы в таком прерывании у Вас должно выполняться больше: принудительная остановка DMA (с ожиданием опустошения FIFO), перепрограммирование DMA на новую посылку и т.д.

И получаем рост загрузки CPU почти в 100 раз по сравнению с вариантом с периодическим IRQ.

 

PS: Заглянул сейчас в даташит на STM32F4, глубоко не вчитывался - искал величину IDLE-time. И нашёл такой пункт:

An Idle character is interpreted as an entire frame of “1”s followed by the start bit of the 
next frame which contains data (The number of “1” ‘s will include the number of stop bits).

"Idle-character" - это и есть оно самое? Тогда получается, что это совсем не для обнаружения таймаута в потоке символов. А для обнаружения 1-го символа после такой паузы. Если поток символов прекратился и новых больше нет, то IDLE-прерывание и не придёт никогда. Да и новый символ после IDLE-прерывания примется даже менее, чем через один символьный интервал, и угроза переполнения ещё больше.

 

Или "Idle-character" - это нечто другое? Где тогда описание, что такое IDLE.IRQ и после какого времени от последнего стоп-бита оно генерится? Больше там ничего не нашёл....  :wacko2:

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


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

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

Если предположить, что по UART у нас ходит не modbus (не надо отлавливать паузы), а какой-то другой протокол, в котором короткие паузы не означают ровным счётом ничего. И не нужна прям мгновенная реакция на завершение кадра

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

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

То можно представить ситуацию, что на вход UART.RX поток символов поступает не тесно (старт-бит сразу за стопом предыдущего), а с паузами между символами чуть больше IDLE-time

В реальной жизни часто такой поток встречали? Только честно. Я - нет.

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

принудительная остановка DMA (с ожиданием опустошения FIFO),

Можно отключить FIFO, ждать не прилдется. В связке с УАПП толку от него не много.

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

Или "Idle-character" - это нечто другое?

Хз что они имели тут ввиду, но на картинке чуть ниже Idle frame изображен как время N+2 битов, т.е. включая стартовый и стоповый. И дальше в тексте упоминается Idle frame.

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


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

Появилась минутка у меня взять да проверить, как IDLE себя ведет.

Настроил прерывание по IDLE и по RXNE, в обработчике лишь следующие строки

void USART1_IRQHandler(void)
{
  u32 sr = USART1->SR;
  
  if(sr & USART_SR_IDLE)
    GPIOG->ODR ^= 1 << 13; // LED toggle
  
  if(sr & USART_SR_RXNE)
    USART1->DR = USART1->DR;
}


С консоли отправляю по одному символу - светодиод переключается через раз... Это значит, что IDLE действительно ничего не отсчитывает от конца последнего символа, а ждет старт-бита следующего байта. Для механизма FIFO, озвученного мной выше, оно не годится. Допустим, имеем буфер DMA на 1 кБ; по UART друг за другом прилетели 100 байт. IDLE не сработает, DMA transfer complete тоже:nea:Значит, таймер.

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


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

33 minutes ago, Сергей Борщ said:

В реальной жизни часто такой поток встречали? Только честно. Я - нет.

Хаха, вот примерно, месяц назад как раз встретил в интерфейсе одного немецкого прибора. Байты с интервалами 20 мс.  

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


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

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

Хаха, вот примерно, месяц назад как раз встретил в интерфейсе одного немецкого прибора. Байты с интервалами 20 мс.  

Ну, все-таки, 20мс это, мягко говоря, вагон времени.

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


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

1 час назад, Сергей Борщ сказал:

В реальной жизни часто такой поток встречали? Только честно. Я - нет.

В реальной жизни ещё и не такое случается. Что будет на входе, как там будет написано (в чужом девайсе, присылающем вам на вход данные) - Вы не знаете. А если оно данные присылает не противореча спецификации, а ваш девайс при этом глючит, то это проблема уже только вашего девайса.

Такая ситуация может быть создана даже преднамеренно. Например: Есть конкурент, цель которого - скомпрометировать ваше устройство, как не соответствующее заявленной задаче, чтобы выиграть у Вас тендер на заказ. Берёт этот конкурент втихаря Ваш девайс, и гоняет его в хвост и в гриву. И выясняет такую особенность, что при определённой временной диаграмме отправки байт, ваше устройство начинает тупить и не успевать обрабатывать данные. Затем он создаёт некое тестовое окружение, преднамеренно отправляющее данные таким образом и проводит официальные испытания вашего устройства. И всё! Протокол по UART соответствует спецификации? Соответствует, ведь он допускает любые паузы между байтами внутри кадра (не превышающими время таймаута), а ваше устройство при этом глючит. Значит ваше устройство не соответствует. Тендер проигран!

Мы с таким сталкивались в реальной жизни. Не именно паузы, но очень близкое - по особенностям работы интерфейсов связи при определённых условиях. Так и сделали конкуренты.

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

 

1 час назад, Сергей Борщ сказал:

Хз что они имели тут ввиду, но на картинке чуть ниже Idle frame изображен как время N+2 битов, т.е. включая стартовый и стоповый. И дальше в тексте упоминается Idle frame.

А Вы то как писали драйвер UART, опирающийся на эти IDLE-прерывания??  :scratch_one-s_head:  Ведь если так, то хвосты кадров внутри границ DMA-блока Вы никогда не будете получать.

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


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

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

А Вы то как писали драйвер UART, опирающийся на эти IDLE-прерывания??

На F100 у меня прерывание IDLE четко срабатывает через время одного байта после окончания стопа от последнего принятого, modbus работает, никто не жалуется, диаграммы как в учебнике. УАПП там вроде практически такой же, как в F4xx. На F0 поведение такое же - хвосты кадров принимаются. Почему у Arlleex не получилось - я не знаю, завтра на работе постараюсь найти время проверить на F407.

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

Ведь если так, то хвосты кадров внутри границ DMA-блока Вы никогда не будете получать.

Или вы что-то поняли не так и теперь пытаетесь нас убедить, что оно работать не может. Просто потому, что вы это не используете.

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


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

51 минуту назад, Сергей Борщ сказал:

Или вы что-то поняли не так и теперь пытаетесь нас убедить, что оно работать не может. Просто потому, что вы это не используете.

В чём и кого я пытаюсь убедить?? :wacko2:  Я вроде только спрашивал Вас. О деталях IDLE. Раз Вы сказали, что используете его и сослались на мануал. Я этот мануал прочитал, и судя по нему - работать как вы утверждаете оно не может. И опять вас спрашиваю - как же так? И если я понял неправильно, то как я должен был понять? - я же Вас как раз об этом спрашивал.

И теперь оказывается я кого там убеждаю в чём-то. Любите вы придумывать чего нет.

Я утверждаю лишь то, что если оно действительно обстоит как написано в мануале, то работать оно как Вы описали просто не может. Это да - утверждаю. Есть возражения?

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


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

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

Я вроде только спрашивал Вас. О деталях IDLE.

Я ответил, что понятия не имею зачем они описали там Idle character, потому что далее везде речь идет об Idle frame, который нарисован на картинке под процитированным вами текстом и который есть время полного байта включая стартовый и стоповый бит. И оно работает именно так, что логично. Почему вы выдумали, что Idle character == Idle frame - я понятия не имею и кому в здравом уме могло бы понадобиться описанное вами поведение IDLE, чтобы конструкторы его реализовали именно так, как вы описали - не могу себе представить.

Хотя, допускаю, что они просто написали глупость в самом первом описании F10x, а потом ее тупо растиражировали в документации на F100, F2xx, F4xx, потому что в описании F0xx УАПП другой и они, вероятно, при переработке описания прочитали текст внимательно и уже убрали упоминание стартового бита следующего байта, хотя картинка ниже осталась та же.

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


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

44 минуты назад, Сергей Борщ сказал:

и кому в здравом уме могло бы понадобиться описанное вами поведение IDLE, чтобы конструкторы его реализовали именно так, как вы описали - не могу себе представить.

Нужно это может быть например для пробуждения устройства из сна при обнаружении начала передачи по UART. На что намекает фраза в самом начале мануала:

Wake up from mute mode (by idle line detection or address mark detection)

И всё логично: тишина на линии -> устройство спит; появилась активность -> надо быстрее просыпаться, сразу по старт-биту.

 

PS: Возможно что такого поведения (прерывания по таймауту неактивности на линии), можно добиться установкой бита RWU. Совместно с разрешением IDLEIE. И тогда прерывание IDLE как раз и будет работать как Вы хотите. Но не уверен - надо более подробно читать и поверять. Кому нужно...

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


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

В F0 есть специальный механизм таймаута (флаг RTOF). Правда, в остальных линейках этого механизма уже, увы, нет.

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


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

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

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

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

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

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

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

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

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

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