|
LPC4337, DMA + SSP, В редких случаях приём не завершается полностью |
|
|
|
Feb 13 2018, 09:08
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
Добрый день, коллеги! Есть связка на приём и передачу через SSP + DMA в упомянутом микроконтроллере. В некоторый момент при тестировании обнаружил, что иногда канал DMA оставляет 4 непринятых байта в регистре CONTROL в поле size. При этом контроллер DMA не выставляет ни одного флага ошибки. Соответственно бит ENABLE этого канала остаётся в единице.
Как устроены транзакции? Есть два канала dma. Канал 2 обслуживает передачу через SSP, канал 0 - приём через SSP (более приоритетный канал на приём). Далее, программируем одинаковое количество байт на передачу, соответственно и на приём тоже. Сначал включаем канал приёма. Затем - канал передачи, и именно по нему ждём завершения транзакции. Подразумевается, что канал приёма их завершит тоже, т.к. шина SSP - синхронная.
В целом всё работает. Запускаю циклический тест (на шине висит флешка). Флешку пишу и читаю из неё. Соответственно адреса буферов всегда одни и теже. На 1000, скажем, транзакций в очень редких случаях происходит описанная проблема.
Я уже умотался искать проблему. Несколько минимизировал её появление, установив burst size в 1 байт на приём и передачу. Если сделать 4 байта, то ошибка проявляется значительно чаще. Коллеги, я просто не понимаю источник ошибки, т.к. не один флаг не взводится. Флаги переполнения FIFO RX у SSP тоже обнулены. Из-за чего так может вести себя дмашник?
Что особенно печалит: я не могу воспроизвести ошибку, и нет флагов ошибки...
P.S. SSP - мастер. CS дёргаю программно, т.к. нужно выдерживать времянки.
P.S.S. 4 байта остатка вовсе не обязательно. Сейчас поймал 3 и 7. P.S.S.S. Есть зависимость от оптимизации компилятора. Можно сказать, что ошибка не появляется, или слииишком редка, если оптимизация 0. И чуть чаще на максимальном уровне оптимизации.
--------------------
Выбор.
|
|
|
|
|
Feb 13 2018, 10:52
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(haker_fox @ Feb 13 2018, 11:08)  Сначал включаем канал приёма. Затем - канал передачи, и именно по нему ждём завершения транзакции. Подразумевается, что канал приёма их завершит тоже, т.к. шина SSP - синхронная. Вроде как должно быть очевидным, что ждать завершения нужно по каналу приёма, но никак не передачи.  Цитата(haker_fox @ Feb 13 2018, 11:08)  Подразумевается, что канал приёма их завершит тоже, т.к. шина SSP - синхронная. Шина синхронная и что с того? Данные на передачу надо сперва записать, а потом они начнут выдвигаться, а на приём наоборот - сперва вдвигаются, а потом появляются в регистре приёма. Цитата(haker_fox @ Feb 13 2018, 11:08)  Коллеги, я просто не понимаю источник ошибки, т.к. не один флаг не взводится. Флаги переполнения FIFO RX у SSP тоже обнулены. Из-за чего так может вести себя дмашник? Как можно не понимать очевидного???  Вы же сами пишете про FIFO. Записали Вы в TX.FIFO последние данные - данных по TX у Вас больше нет, Вам приходит событие о завершении TX DMA-пересылки. Вы режете канал. А в это время SSP продолжает передачу из TX.FIFO находящихся там данных (ну и соответственно - приём в RX.FIFO). Вроде должно быть очевидным, что работу с SSP нужно всегда завершать по завершению RX блока. Даже без FIFO.
|
|
|
|
|
Feb 13 2018, 12:53
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (jcxz @ Feb 13 2018, 20:38)  Потому что выключаете SSP Вы видимо в ISR, который активизируется завершением DMA? Я не выключаю SSP. SSP всегда включен. Перед транзакцией разрешатся всегда передача через DMA. А вот канал приёма DMA включатся только в том случае, если принятые данные нужны. Иногда же данные достаточно просто передать, а ничего вычитывать из слейва не требуется. В начале каждой транзакции через шину я вычитываю FIFO буфер SSP, т.к. там есть данные, если в предыдущей транзакции мы не использовали данные от слейва. Также очищаю флаг OVERRUN. В связи с этим понимаю, что зря NXP не сделала возможность отключить приёмник SSP. И всегда приходится вычитывать его FIFO. Ну и включив передающий канал ДМА (предварительно включив, если требуется принимающий), я разу же жду события от прерывания TC (по передаче). Как только оно наступает, я читаю, что все транзакции на шине закончились.
--------------------
Выбор.
|
|
|
|
|
Feb 13 2018, 13:19
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(haker_fox @ Feb 13 2018, 14:53)  Я не выключаю SSP. SSP всегда включен. ... я разу же жду события от прерывания TC (по передаче). Как только оно наступает, я читаю, что все транзакции на шине закончились. Под выключением я имел в виду вот именно это. Назовите это хоть остановом хоть ещё как. Неправильно считаете. Прерывание об окончании передачи TX.DMA говорит только о том, что закончена передача данного блока DMA из памяти в целевую периферию (в целевой адрес периферии было записано последнее слово из FIFO DMA-канала). Вы же получаете прерывание о завершении от DMA, а не от SSP, с чего тогда Вы решили что SSP закончил свою работу??? Если Вы запишете слово в выходной TX-буфер SSP процессором без DMA, Вы тоже будете считать что передача по SPI закончилась в момент завершения выполнения команды записи? Она ещё может даже не начаться. Точно так же - и в момент завершения передачи TX-DMA блока передача по SPI ещё может даже не начаться. Поэтому судить можно только по завершению RX.DMA. Именно поэтому и NXP не сделала отключения приёмника ибо - нафиг это не нужно. Потому что приёмный канал в любом случае нужен для нормального обнаружения завершения транзакции.
|
|
|
|
|
Feb 13 2018, 13:45
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(haker_fox @ Feb 13 2018, 15:25)  З.Ы. Мне одному кажется, что из одного только юзер мануала на микроконтроллер не следует всего того, что вы сказали? Что это? Многолетний опыт работы с различными микроконтроллерами? Или я за соснами леса не вижу?  Честно говоря - не знаю. Я конечно много лет работал с разными LPC - от LPC23xx (старых ещё), до LPC43xx. И ничего кроме мануалов на них не читал. Но впрочем это ведь касается не только NXP: такой алгоритм работы, он справедлив для всех МК с SPI, везде аналогично - что у TI, что у STM, что у Infenion, .... Это вытекает из принципа работы самого SPI: чтобы что-то передать, надо вначале это что-то записать в буферный регистр, а чтобы что-то принять нужно сначала чтобы прошло нужное число клоков SCLK. Т.е. - события записи передаваемого слова в TX-буфер и появления принятого слова в RX-буфере - никак не могут быть одновременными явлениями. И FIFO тут не при чём. Даже собственно на уровне одного бита - нужно его сперва выставить на шину и только потом - сэмплировать приёмником. Поэтому и писал, что эти вещи мне кажутся очевидными.
|
|
|
|
|
Feb 13 2018, 16:07
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(haker_fox @ Feb 13 2018, 16:34)  Ну воот  Про это мне совсем не известно... нужно, значит, ещё и команды дополнительные вставлять... если не сложно, можете чуть по-подробнее рассказать? Если Вы записали что-то в регистры некоей периферии, а затем - в регистры другой периферии. И вторая запись - запускает взаимодействие 2-й периферии с первой, то между первой записью и 2-й записью необходимо вставить DMB. Иначе будет то работать, то глючить. Если к примеру какая-то запись в регистр периферии включает её работу, и эта периферия сразу посылает запрос DMA-каналу. А до этого вы конфигурили данный DMA-канал, и в процессе конфигурирования очистили регистр DMA-запросов, то возможна ситуация, что конфигурация DMA-канала запишется в него после того, как включится периферия его использующая. И например запрос к DMA от периферии потеряется и она вечно будет ждать обслуживания со стороны DMA-канала. DMB устраняет эту проблему. Ну или другой вариант: Вы в регистре флагов запросов прерываний некоей периферии почистили флажки, потом почистили их в NVIC (перед тем как размаскировать), а потом размаскировали данное прерывание в NVIC. И оно тут же произошло (прерывание). Хотя ещё никакой активности с периферией не было. Просто Ваша команда очистки флажков дошла до периферии позже чем команда очистки флажков в NVIC. И NVIC успел опять защёлкнуть запрос прерывания.
|
|
|
|
|
Feb 15 2018, 00:13
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (jcxz @ Feb 14 2018, 23:14)  Никак. Всегда программировать RX-DMA-канал. Не понимаю - а зачем Вы упорно пытаетесь обойтись без приёма? 1 DMA канал сэкономить? Нет. Сложновато получается. Допустим, мне надо только передать 10 кб по связанному списку. Значит приём "холостых" байт нужно вести в какой-то закольцованный связным списком буфер?! Вот мне это и кажется избыточным. Видимо придётся делать. QUOTE (jcxz @ Feb 14 2018, 23:14)  И приоритет RX-DMA-канала всегда должен быть выше чем у TX-DMA. Да-да, это я уже сделал) Стоп!!! Это что же такое я говорю, совсем заработался. Не надо на приём делать холостой связный списко. Можно просто не инкрементировать адрес приёмника в дма, и лишь хоть весь объём Вселенной в буфер из одного байта))))))
--------------------
Выбор.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|