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

avg33

Участник
  • Постов

    12
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный

Посетители профиля

241 просмотр профиля
  1. Если дословно: "The peripheral resource (I/O) requests DMA transfer by asserting an interrupt". У DMA канала есть регистр, в котором указывается номер прерывания, которое инициирует передачу. То есть, если настроить DMA канал на прерывание RX, то event "регистр-приемник полный" инициирует прерывание RX, которое уйдет не в контроллер, а в DMA. DMA прочитает байт из регистра-приемника USART и уменьшит счетчик прочитанных байт. Если счетчик обнулился, DMA передает запрос на прерывание контроллеру и тот вызывает обработчик RX. Вот блок-схема из документации: Так вот, время от времени возникает ситуация, что отправил я 1029 байт, а получил якобы только 1028. В этот момент счетчик переданных байт = 0, прочитанных = 1. Соответственно и обработчик RX не вызывается и я не могу завершить транзакцию чтения. Хотя последний байт пришел, я вижу его в регистре приемника. Получается по каким-то причинам DMA не обнулил счетчик (прерывание не пришло?) А поциент jcxz выше явно забежал сюда меня потроллить, вот и разводит бесполезный флуд вокруг терминологии :rolleyes: F2MC-16FX MB96600 Series http://www.cypress.com/file/241411/download Как оказалось, приоритеты каналов тут ни при чем. И новая и старая версии чтения дают сбой при запуске прошивки через отладчик. Если запускаю без отладчика все работает без сбоев. Отладчик может влиять на процесс? Я в курсе, что вы не знаете. И сарказма тоже не понимаете, как я вижу. Ну раз не знаете, то и не надо меня убеждать, что я что-то путаю и не понимаю работу своего контроллера. Если не долбиться в глаза можно увидеть вопросы, которые я задавал. Возможно, у кого-то была похожая проблема. Может быть, у кого-то отладчик тоже влиял на работу и тд. Вас лично никто отвечать не заставляет
  2. Очень мало - это сколько?)))) Вы с кем общаетесь? Сам с собой?) Объясняю еще раз. В моем контроллере периферия запрашивает передачу DMA путем установки прерывания. Не знаю, как это устроено в других контроллерах - в моем именно так. Чтобы начать DMA передачу нужен запрос прерывания от периферии. Если канал DMA включен и настроен на прерывание, то запрос этого прерывания заставляет DMA начать передачу. После передачи элемента (байт/слово) возможны ситуации: 1. Счетчик переданных данных > 0 - DMA очищает запрос прерывания от периферии и ждет нового 2. Счетчик ==0 - DMA передает запрос прерывания контроллеру прерываний. Вызывается обработчик. То есть, если надо отправить байты - я должен настроить DMA канал на прерывание TX и разрешить его (прерывание). Как только прерывание TX разрешено - возникает запрос на TX прерывание и начинается передача. После передачи блока вызовется обработчик прерывания TX. Аналогично с чтением. Стоит ли объяснять как я организую SPI обмен? Я настраиваю один канал на передачу, другой на чтение и разрешаю прерывания RX и TX. Как только передано/прочитано нужное число байт вызываются обработчики прерываний TX/RX. Это к вашему вопросу "а зачем вам TX прерывание". Если знаете как запустить передачу без него в текущих условиях - поделитесь примером Я обмениваюсь информацией с флэшкой. Об этом было написано в самом начале. Ну в чем-то штатный, а в чем-то нет. Ну либо разрабы этого камня дураки и вообще все организовали не правильно (судя по вашим словам). Я в общем-то и делаю по примерам. Не надо меня держать за дурака. Просто примера SPI обмена через DMA нет. Есть только пример передачи. От него и отталкиваюсь в написании кода Видимо точно что-то с прерываниями. Выше писали, что приоритет канала RX должен быть выше, чем канала TX. Потому что запросы DMA по RX должны обрабатываться в первую очередь. У меня так и было сделано. Но вот вчера вечером уже от безысходности поменял DMA каналы местами. Теперь у чтнения приоритет ниже, чем у отправки. И вот уже несколько часов непрерывного чтения и ни одной ошибки (раньше хватало на несколько минут или даже секунд). Понять бы природу странности, ведь по опыту людей все должно быть ровно наоборот. В даташите толком ничего не написано и примеров нет
  3. Да, видимо что-то делаю не так. Буду признателен, если покажете рабочий пример SPI обмена по DMA. Любого контроллера. Хочу понять принцип. Вы не первый кто пишет, что TX прерывание не нужно. Но я не могу начать передачу по DMA, не разрешив TX прерывание. После отправки последнего байта DMA передает пришедший запрос на прерывание контроллеру - вот и вызывается обработчик. Как же от этого уйти?
  4. спасибо, с интересом почитал. но сколько не бился ничего не помогает. приоритет на чтение у меня, кстати, выше. не пойму в чем может быть дело
  5. Убрать похоже что не получится, без него DMA не начнет передачу. Можно только обработчик оставить пустым, но это бессмысленно. Сейчас в обработчике я сбрасываю флаг разрешения прерывания, иначе обработчик будет вызываться вечно Как это работает (как я понял из даташита): 1. Аппаратный флаг TX USART по умолчанию равен 1 - он инициирует запрос на прерывание. если оно разрешено 2. Настраиваю DMA на передачу 3. Устанавливаю в 1 флаг разрешения прерывания по TX 4. Флаг TX USART инициирует запрос на прерывание, который пинает DMA. DMA начинает передачу и после обнуления счетчика передает запрос на прерывание контроллеру, запускается обработчик 5. В обработчике вручную сбрасывается флаг разрешения прерывания, чтобы запрос на прерывание больше не возникал (иначе после выхода из обработчика я снова в него попаду). И выключается DMA канал То есть максимум, что можно сделать - это убрать из обработчика IRQ TX отключение канала DMA по передаче и вынести это в обработчик IRQ RX. В моем контроллере прерывания USART TX и USART RX устроены точно так же. Почему-то не предусмотрел этот момент)) Возможно, дело именно в этом. Сейчас почитал даташит, оказывается есть возможность инициировать прерывание USART TX после передачи последнего бита байта из сдвигового регистра на шину. Попробую поэкспериментировать с обработчиком, потом с механизмом прерывания и посмотреть, что происходит. Спасибо за помощь, мне как-то даже не пришла в голову эта версия))
  6. я не могу понять, если байт потерялся, то разве не должно возникнуть ошибки переполнения? потерялся - это же значит пришел, но не был вычитан. есть еще вариант, что он пришел, но аппаратный флаг не поднялся и не пнул DMA. но это выглядит фантастикой пока что я читаю только при включении девайса. можно много раз включать/выключать пока ошибка не появится. последний раз мне вообще не удалось отловить этот момент 1. Да, чем ниже номер канала, тем выше приоритет доступа. Читаю я по 2 каналу, передаю по 3. По идее, у чтения приоритет выше 2. Увеличить уже никак. Скорость 4 млн бод. Попробую уменьшить 3. Обработчик прерывания по передаче по идее мне вообще не нужен. Из флэш я просто читаю) Но если его выкинуть, то придется очищать флаг разрешения прерывания TX и отключать соответствующий канал в обработчике прерывания по RX. Это нормально?
  7. Всмысле телепаты?)) Если вы про код, то он простейший, алгоритм описан выше. А контроллер специфический, вряд ли кто-то будет разбираться в тамошних регистрах и тд Без DMA делал только отправку на этапе отладки (читаю всегда по DMA). Подобных ошибок не замечал Вообще много раз читал что-то без DMA - никогда не было подобных проблем
  8. Я общаюсь с 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 байта. Байт ведь не мог "потеряться". Или мог? В чем может быть причина такого поведения? Повторюсь, ошибка проявляется крайне редко, в остальном алгоритм четко работает
  9. 1. По совету Arlleex переместил снятие CS из прерывания по передаче IRQ_TX() в прерывание по чтению IRQ_RX() 2. Обнаружено, что с флешки на ножку контроллера RX приходит 3.3V, а контроллер работает с 5V. На всякий случай на вывод флешки был вкорячен подтягивающий резистор После этого стало намного лучше. Но на скоростях >12000 бод время от времени в буфере продолжали появляться невалидные данные. При этом у проблемы появилась системность: на очередном чтении буфер сначала целиком заполнялся 0xFF (это уровень на линии по умолчанию), а следующая итерация чтения давала либо то же самое, либо читала что-то похожее на правду, но гарантированно устанавливала ORE. Порывшись в отладчике стало ясно, что к данному глюку приводит ситуация, когда прерывание по чтению IRQ_RX() вызывается раньше, чем прерывание по передаче IRQ_TX(). В IRQ_TX() у меня только снятие флага прерывания по передаче и отключение канала DMA. Не совсем понимаю, как это может вызвать забиваение буфера в 0xFF после очередного вызова read(), но четкая связь на лицо. В общем, мне нужно сделать так, чтобы IRQ_TX() гарантированно вызывался раньше, чем IRQ_RX(). Я попробовал назначить IRQ_TX() более низкий приоритет и, кажется, это работает. Насколько надежен и адекватен такой метод или лучше разрешить данную ситуацию как-то иначе через извращения в коде?
  10. Заметил, что если поставить точку останова в IRQ_TX(), то на этот момент ORE уже стоит. И если DMA что-то не успел дописать в буфер, то с этого байта в буфере будет мусор из повторяющегося значения входного регистра. А еще бывает мусор в начале буфера и его на ORE никак не списать, ибо дальше идут данные валидные. Черт знает вообще откуда это все берется
  11. Arlleex, благодарю за оперативный ответ. F2MC-16FX MB96600 Series И вправду. А если снять его в IRQ_RX() ? По идее прерывание по приему должно сработать после того, как DMA переложит последний байт в буфер. Или там тоже нюансы со сдвиговым регистром? По передаче или приему? Или и то и другое?) Я просто указал DMA сколько и откуда писать, куда читать, по каким перываниям срабатывать. Даже не знаю, где там можно ошибиться
  12. Всем привет. Пытаюсь прочитать SPI флэшку по DMA. Работаю через USART. Суть дела в следующем. Допустим, буду читать из флэш по 100 байт. Для этого надо отправить на флэш 105 байт: 5 байт команды и 100 байт фиктивной записи. Сначала я повесил прием на 2 канал DMA, а запись во флэш реализовал прямо в цикле for: Такой сценарий нормально работает. И при одиночном и при повторном вызове read() в rx_buf лежат валидные данные: 5 байт 0xFF и 100 байт из флэш Но писать через for долго. Поэтому передачу tx_buf я тоже повесил на канал DMA: И вот этот сценарий дает сбой. Проблема в том, что в какой-то момент устанавливается в 1 флаг переполнения ORE USART`а. Соответственно, в rx_buf по окончанию приема лежат невалидные данные. Обычно в конце буфера какая-то чушь, иногда в начале или вообще весь буфер бред. Бывает и такое, что первый вызов read() дает корректные данные, но второй всегда невалидные. Момент выставления ORE в единицу уловить невозможно, я так и не выявил зависимости. Что я делаю не так, в чем может быть проблема?
×
×
  • Создать...