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

Не срабатывает прерывание при чтении по DMA

Я общаюсь с SPI флэшкой через USART в синхронном режиме. Передача и прием организованы по DMA каналам. Посылки фиксированной длины (1024 байта).

Алгоритм обмена выглядит так:

1. Активирую флэш (CS=0)

2. Настраиваю DMA канал на прием 1024 байт. Разрешаю прерывание по чтению IRQ_RX

3. Настраиваю другой DMA канал на передачу 1024 байт. Разрешаю прерывание по передаче IRQ_TX - в этот момент начинается передача/прием

4. В обработчике IRQ_TX очищаю флаг разрешения прерывания, отключаю DMA канал передачи

5. В обработчике IRQ_RX очищаю флаг разрешения прерывания, отключаю DMA канал чтения + деактивирую флэш (CS=1)

 

Ну то есть стандартный SPI обмен: посылаю 1024 байта - одновременно принимаю 1024 байта. По окончанию передачи/приема обрабатываю прерывания.

 

И все вроде бы работает. Но иногда (очень и очень редко) бывает ситуация, когда прерывание по передаче срабатывает, а прерывание по чтению нет!

Что я вижу в дебагере в этот момент:

1. Счетчик DMA по передаче равен 0, а по чтению 1. То есть DMA отправил 1024 байта, а прочитал почему-то только 1023. Соответственно, прерывание по чтению не сработает никогда.

2. Ошибки переполнения при чтении (overrun error) нет. Все флаги ошибок равны 0.

3. В регистре чтения USART лежит последний байт посылки (0x89). То есть последний (1024-й) байт посылки похоже таки пришел в регистр. Но счетчик не обнулился

4. Аппаратный флаг прерывания по чтению равен 0. То есть, последний байт был вычитан из регистра буфер. Либо он даже не устанавливался в 1, когда последний байт пришел в регистр

 

Не могу понять чем это все вызвано. Ведь если отправлено 1024 байта, то и прочитать шина должна была 1024 байта. Байт ведь не мог "потеряться". Или мог? В чем может быть причина такого поведения?

Повторюсь, ошибка проявляется крайне редко, в остальном алгоритм четко работает

Изменено пользователем avg33

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


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

Я общаюсь с SPI флэшкой через USART в синхронном режиме.

В Вашем теле есть усарт да еще и синхронный? :biggrin:

А так то да. Телепаты вот вот подтянутся.

Без DMA пробовали гонять?

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


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

В Вашем теле есть усарт да еще и синхронный? :biggrin:

А так то да. Телепаты вот вот подтянутся.

Без DMA пробовали гонять?

 

Всмысле телепаты?)) Если вы про код, то он простейший, алгоритм описан выше. А контроллер специфический, вряд ли кто-то будет разбираться в тамошних регистрах и тд

 

Без DMA делал только отправку на этапе отладки (читаю всегда по DMA). Подобных ошибок не замечал

Вообще много раз читал что-то без DMA - никогда не было подобных проблем

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


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

В регистре чтения USART лежит последний байт посылки (0x89). То есть последний (1024-й) байт посылки похоже таки пришел в регистр. Но счетчик не обнулился

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

Может это прояснит ситуацию.

(очень и очень редко)

раз в час? в столетие? или реже?

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


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

В чём может быть дело не знаю. Тем более не известно какой контроллер :laughing:

 

Мои варианты:

1. Попробуйте поменять местами каналы DMA: тот что был для RX сделать для TX, и наоборот. Если каналов DMA больше 2-х, попробуйте и остальные.

(что-то, где-то читал, про приоритет каналов DMA на доступ к внутренней шине данных).

2. Уменьшите скорость SPI - например в 2 раза. Может пары дополнительных тактов хватит для "разруливания" ситуации? Также увеличьте скорость SPI ещё больше (если настройки позволяют) - не будет ли ошибка проявляться ещё чаще?

3. Попробуйте для режима чтения оставить прерывание только по RX, а для записи только по TX. Всё равно сразу два прерывания в каждом из режимов лишние, но вдруг это тоже что-то выявит.

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


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

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

Может это прояснит ситуацию.

 

раз в час? в столетие? или реже?

я не могу понять, если байт потерялся, то разве не должно возникнуть ошибки переполнения?

потерялся - это же значит пришел, но не был вычитан. есть еще вариант, что он пришел, но аппаратный флаг не поднялся и не пнул DMA. но это выглядит фантастикой

 

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

 

 

В чём может быть дело не знаю. Тем более не известно какой контроллер :laughing:

 

Мои варианты:

1. Попробуйте поменять местами каналы DMA: тот что был для RX сделать для TX, и наоборот. Если каналов DMA больше 2-х, попробуйте и остальные.

(что-то, где-то читал, про приоритет каналов DMA на доступ к внутренней шине данных).

2. Уменьшите скорость SPI - например в 2 раза. Может пары дополнительных тактов хватит для "разруливания" ситуации? Также увеличьте скорость SPI ещё больше (если настройки позволяют) - не будет ли ошибка проявляться ещё чаще?

3. Попробуйте для режима чтения оставить прерывание только по RX, а для записи только по TX. Всё равно сразу два прерывания в каждом из режимов лишние, но вдруг это тоже что-то выявит.

1. Да, чем ниже номер канала, тем выше приоритет доступа. Читаю я по 2 каналу, передаю по 3. По идее, у чтения приоритет выше

2. Увеличить уже никак. Скорость 4 млн бод. Попробую уменьшить

3. Обработчик прерывания по передаче по идее мне вообще не нужен. Из флэш я просто читаю) Но если его выкинуть, то придется очищать флаг разрешения прерывания TX и отключать соответствующий канал в обработчике прерывания по RX. Это нормально?

Изменено пользователем avg33

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


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

3. Обработчик прерывания по передаче по идее мне вообще не нужен. Из флэш я просто читаю) Но если его выкинуть, то придется очищать флаг разрешения прерывания TX и отключать соответствующий канал в обработчике прерывания по RX. Это нормально?

Да, попробуйте убрать прерывание для TX канала DMA совсем. Флаг TX USART в режиме DMA обычно сбрасывается автоматически, поэтому дублировать его сброс программно не нужно. Зато есть такой нюанс:

В большинстве известных мне контроллеров, прерывание USART TX происходит в начале передачи байта (буфер TX переписали в регистр сдвига - и тут же прерывание TX), а прерывание USART RX происходит в конце приёма байта (из регистра сдвига переписали в буфер RX - и только тогда прерывание RX). Если USART отключить по прерыванию TX, то прерывание на приём последнего байта пакета может не наступить. И канал DMA RX, соответственно, запрос на последний байт не получит.

Изменено пользователем controller_m30

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


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

Да, попробуйте убрать прерывание для TX канала DMA совсем. Флаг TX USART в режиме DMA обычно сбрасывается автоматически, поэтому дублировать его сброс программно не нужно

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

Как это работает (как я понял из даташита):

1. Аппаратный флаг TX USART по умолчанию равен 1 - он инициирует запрос на прерывание. если оно разрешено

2. Настраиваю DMA на передачу

3. Устанавливаю в 1 флаг разрешения прерывания по TX

4. Флаг TX USART инициирует запрос на прерывание, который пинает DMA. DMA начинает передачу и после обнуления счетчика передает запрос на прерывание контроллеру, запускается обработчик

5. В обработчике вручную сбрасывается флаг разрешения прерывания, чтобы запрос на прерывание больше не возникал (иначе после выхода из обработчика я снова в него попаду). И выключается DMA канал

 

То есть максимум, что можно сделать - это убрать из обработчика IRQ TX отключение канала DMA по передаче и вынести это в обработчик IRQ RX.

 

Зато есть такой нюанс:

В большинстве известных мне контроллеров, прерывание USART TX происходит в начале передачи байта (буфер TX переписали в регистр сдвига - и тут же прерывание TX), а прерывание USART RX происходит в конце приёма байта (из регистра сдвига переписали в буфер RX - и только тогда прерывание RX). Если USART отключить по прерыванию TX, то прерывание на приём последнего байта пакета может не наступить. И канал DMA RX, соответственно, запрос на последний байт не получит.

В моем контроллере прерывания USART TX и USART RX устроены точно так же. Почему-то не предусмотрел этот момент)) Возможно, дело именно в этом.

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

 

Попробую поэкспериментировать с обработчиком, потом с механизмом прерывания и посмотреть, что происходит. Спасибо за помощь, мне как-то даже не пришла в голову эта версия))

Изменено пользователем avg33

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


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

Почитайте мои пути про SPI + DMA. Там LPC4337, но вдруг поможет. Логика, в целом, одинаковая.

1. https://electronix.ru/forum/index.php?showt...=145765&hl=

2. https://electronix.ru/forum/index.php?showt...=146837&hl=

 

В кратце: приоритет канала на приём (RX) должен быть выше (выше!!!), чем приоритет канала на передачу!

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


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

Почитайте мои пути про SPI + DMA. Там LPC4337, но вдруг поможет. Логика, в целом, одинаковая.

1. https://electronix.ru/forum/index.php?showt...=145765&hl=

2. https://electronix.ru/forum/index.php?showt...=146837&hl=

 

В кратце: приоритет канала на приём (RX) должен быть выше (выше!!!), чем приоритет канала на передачу!

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

 

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


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

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

Значит Вы чего-то не понимаете в работе периферии своего МК. И не зная Ваш МК никто тут не сможет помочь.

Кстати, непонятно - зачем и TX-прерывания и RX? При работе с SPI обычно достаточно или того или другого (обычно RX), но никак не вместе.

Да и судя по сообщениям, Вы путаете прерывания с DMA-запросами. Это вообще то совершенно разные вещи.

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


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

Значит Вы чего-то не понимаете в работе периферии своего МК. И не зная Ваш МК никто тут не сможет помочь.

Кстати, непонятно - зачем и TX-прерывания и RX? При работе с SPI обычно достаточно или того или другого (обычно RX), но никак не вместе.

Да и судя по сообщениям, Вы путаете прерывания с DMA-запросами. Это вообще то совершенно разные вещи.

Да, видимо что-то делаю не так. Буду признателен, если покажете рабочий пример SPI обмена по DMA. Любого контроллера. Хочу понять принцип.

Вы не первый кто пишет, что TX прерывание не нужно. Но я не могу начать передачу по DMA, не разрешив TX прерывание.

После отправки последнего байта DMA передает пришедший запрос на прерывание контроллеру - вот и вызывается обработчик. Как же от этого уйти?

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


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

Буду признателен, если покажете рабочий пример SPI обмена по DMA. Любого контроллера. Хочу понять принцип.

Может не помочь, если речь конкретно о прерывании. Если не знаешь тип контроллера.

У меня была похожая ситуация с миландровским Кортексом, он по SPI управляет DDSом. По итогу отказался обрабатывать прерывания от DMA в их контроллере. Описание там очень плохое, и непонятно, глюк в самом контроллере или в моем понимании работы этого контроллера.

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


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

Да, видимо что-то делаю не так. Буду признателен, если покажете рабочий пример SPI обмена по DMA. Любого контроллера. Хочу понять принцип.

А чем Вам поможет как это сделано в каком-то левом МК? Если даже разберётесь в десятках КБ кода...

В разных МК работа DMA-периферия организована по-своему.

 

Вы не первый кто пишет, что TX прерывание не нужно. Но я не могу начать передачу по DMA, не разрешив TX прерывание.

Вы опять путаете и себя и всех. Прерывания (от периферийного блока) к работе DMA имеют очень мало отношения. Прерывание - это сигнал идущий от периферийного блока к контроллеру прерываний, запрос DMA - сигнал идущий от периферийного блока к DMA-контроллеру. И это как правило - разные сигналы. Более того - в некоторых МК есть несколько разных DMA-запросов (single- и burst-).

Во многих МК прерывания от периферии (если она работает через DMA) вообще следует запрещать (например так в LPC, XMC4xxx), а обрабатывать прерывания от DMA-канала.

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

 

После отправки последнего байта DMA передает пришедший запрос на прерывание контроллеру

Пришедший откуда и куда? На какой контроллер передаёт? У Вас каша в голове, Вы не понимаете как работает система прерываний и DMA в вашем МК. Читайте мануал на МК.

В большинстве МК, с которыми я работал, при работе некоей периферии через DMA, прерывания от неё запрещались, а разрешалось прерывание от DMA-канала, о завершении пересылки блока (или очередного блока).

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

Это - штатный механизм работы через DMA.

И поищите примеры работы с DMA для своего секретного МК.

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


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

Прерывания (от периферийного блока) к работе DMA имеют очень мало отношения.

Очень мало - это сколько?))))

 

Прерывание - это сигнал идущий от периферийного блока к контроллеру прерываний, запрос DMA - сигнал идущий от периферийного блока к DMA-контроллеру. И это как правило - разные сигналы

Вы с кем общаетесь? Сам с собой?) Объясняю еще раз.

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

1. Счетчик переданных данных > 0 - DMA очищает запрос прерывания от периферии и ждет нового

2. Счетчик ==0 - DMA передает запрос прерывания контроллеру прерываний. Вызывается обработчик.

То есть, если надо отправить байты - я должен настроить DMA канал на прерывание TX и разрешить его (прерывание). Как только прерывание TX разрешено - возникает запрос на TX прерывание и начинается передача. После передачи блока вызовется обработчик прерывания TX. Аналогично с чтением.

Стоит ли объяснять как я организую SPI обмен? Я настраиваю один канал на передачу, другой на чтение и разрешаю прерывания RX и TX. Как только передано/прочитано нужное число байт вызываются обработчики прерываний TX/RX.

Это к вашему вопросу "а зачем вам TX прерывание". Если знаете как запустить передачу без него в текущих условиях - поделитесь примером

 

Пришедший откуда и куда? На какой контроллер передаёт?

Я обмениваюсь информацией с флэшкой. Об этом было написано в самом начале.

Это - штатный механизм работы через DMA.

И поищите примеры работы с DMA для своего секретного МК.

Ну в чем-то штатный, а в чем-то нет. Ну либо разрабы этого камня дураки и вообще все организовали не правильно (судя по вашим словам).

Я в общем-то и делаю по примерам. Не надо меня держать за дурака. Просто примера SPI обмена через DMA нет. Есть только пример передачи. От него и отталкиваюсь в написании кода

 

Может не помочь, если речь конкретно о прерывании. Если не знаешь тип контроллера.

У меня была похожая ситуация с миландровским Кортексом, он по SPI управляет DDSом. По итогу отказался обрабатывать прерывания от DMA в их контроллере. Описание там очень плохое, и непонятно, глюк в самом контроллере или в моем понимании работы этого контроллера.

Видимо точно что-то с прерываниями. Выше писали, что приоритет канала RX должен быть выше, чем канала TX. Потому что запросы DMA по RX должны обрабатываться в первую очередь. У меня так и было сделано.

Но вот вчера вечером уже от безысходности поменял DMA каналы местами. Теперь у чтнения приоритет ниже, чем у отправки. И вот уже несколько часов непрерывного чтения и ни одной ошибки (раньше хватало на несколько минут или даже секунд). Понять бы природу странности, ведь по опыту людей все должно быть ровно наоборот. В даташите толком ничего не написано и примеров нет

Изменено пользователем avg33

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


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

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

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

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

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

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

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

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

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

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