KnightIgor 2 13 сентября, 2013 Опубликовано 13 сентября, 2013 · Жалоба Может кто сталкивался. SPI передает и принимает с использованием DMA. Очевидно, что для приема надо передавать хоть что-то (суть SPI), что я делаю с помощью двух каналов DMA: - каналы приема (RX) и передачи (TX) взводятся, при этом в оба загружаются, естественно, одинаковые счетчики. - толкается DMA TX. - ожидается завершение DMA RX. Так вот, иногда (не воспроизводимо и спорадически) из цикла ожидания можно и не выйти, а если прервать, то наблюдается следующее состояние: - канал TX выплюнул всё (его счетчик 0). - канал RX еще ждет, т.к. его счетчик равен 1, - в SPI установлен бит переполнения по приему. Из этого я делаю вывод, что приемный DMA в какой-то момент не успел выбрать байт из RX, а очередная передача успела напихать ему следующий байт. Я предполагал такую ситуацию, почему и повысил приоритет приемного канала (в экспериментах - даже до максимально возможного) относительно передающего, но спорадически зависание-таки имеет место. Частота процессора: от 24 до 48MHz (переключаю выше, когда подсоединяется USB), частота SPI1 12MHz или 24MHz соответственно. SPI работает с SPI flash, которая может от 25MHz и выше. Есть идеи? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 13 сентября, 2013 Опубликовано 13 сентября, 2013 · Жалоба А на <12MHZ работает? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 13 сентября, 2013 Опубликовано 13 сентября, 2013 · Жалоба А на какой частоте работает ДМА выясняли? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 13 сентября, 2013 Опубликовано 13 сентября, 2013 · Жалоба Есть идеи? Когда занимался с таймером и DMA обнаружил, что от момента старта DMA до момента DMA-транзакции проходит более 12 тактов. Этот момент даже где-то описан в документации. Думаю, проблема в старте DMA, когда приходит первый байт, запускается DMA, но сама DMA-транзакция наступает спустя 12 тактов. За это время уже успувает придти второй байт. С позиций передатчика выглядит так: первый байт отправляется с паузой 12 тактов, а второй и последующие без пауз. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KnightIgor 2 13 сентября, 2013 Опубликовано 13 сентября, 2013 (изменено) · Жалоба А на какой частоте работает ДМА выясняли? Я ее не мерял, но судя по схеме в документации (стр. 90 Doc ID 13902 Rev 12 для STM32F10x) они тактируются частотой AHB, то есть ядра. В моем случае это 24 или 48MHz. А на <12MHZ работает? Имеется ввиду SPI? Нет, не понижал. Однако наверняка будет работать стабильней, т.к. частота ошибки растет с увеличением частоты SPI (как я писал, SPI у меня - половина такта процессора). Но понижение частоты - не решение, пока не разобрался с первопричиной. Думаю, adnega здесь привел самую разумную гипотезу с первоначальной задержкой DMA. Потому и отличие всего в один байт в итоге. Ведь и готовность приема возникает на один SPI такт позже, чем готовность передатчика. То есть, SPI уже начала передачу второго байта, а флаг RXNE только взводится. То есть, при 24MHz SPI остается всего 292нс (7 битов) на то, чтобы вычитать принятый байт, пока он не затерся новым. У меня в системе есть еще другой DMA, который обслуживает ADC. Он тоже на шину лезет, хотя приоритет его и ниже читающего из SPI. Но ведь и на арбитраж время нужно... Вот походил, подумал о work around. Если изначально загрузить в TX DMA счетчик 1, разрешить прерывание по TC, пихнуть DMA и в прерывании дозагрузить счетчик N-1, то этим можно ввести паузу между первым и последующими байтами. Изменено 13 сентября, 2013 пользователем KnightIgor Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 14 сентября, 2013 Опубликовано 14 сентября, 2013 (изменено) · Жалоба Думаю, adnega здесь привел самую разумную гипотезу с первоначальной задержкой DMA. Потому и отличие всего в один байт в итоге. Ага, щаз. Сколько пройдет тактов при передаче байта? Правильно, 16. :) Т.е. 4 такта на собсна fetching все-же есть. А пробовали заглушить АЦП-DMA? ЗЫ я имею ввиду - если толкать DMA таким образом DMA1_Channel5->CMAR = (uint32_t) buffer + 1; DMA1_Channel5->CNDTR = size-1; SPI2->DR = *buffer; DMA1_Channel5->CCR |= DMA_CCR5_EN; Изменено 14 сентября, 2013 пользователем _Pasha Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nx6310 0 14 сентября, 2013 Опубликовано 14 сентября, 2013 · Жалоба Я для приема по spi через dma просто перевожу spi в режим приемника. тогда на sclk spi идут постоянные клоки. Соответственно нет необходимости в передаче по spi. Здесь в какой то ветке про это писали. По завершению приема надо spi переводить в режим приемо-передатчика. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 14 сентября, 2013 Опубликовано 14 сентября, 2013 · Жалоба Ага, щаз. Сколько пройдет тактов при передаче байта? Правильно, 16. :) Т.е. 4 такта на собсна fetching все-же есть. А пробовали заглушить АЦП-DMA? Чаще всего 12 тактов, но иногда и больше. Делал светодиодное табло с динамической индикацией: видеопамять с помощью таймеров (каскадное соединение), SPI и DMA передавалась в светодиодную панель. И вроде все хорошо и согласуется с теорией, но иногда были не то проблескивания, не то сдвиги столбцов и строк... Очень редко, очень неуловимо, но когда понял что к чему, оказалось что есть задержка 12 тактов, но иногда (и именно в этих случаях были проблемы) больше 12. DMA был настроен на SPI_TX. Необходимые стробы формировались таймером. Задержка в первом байте на 12 тактов могла означать сдвиг на фиксированное число точек (в моем случае на 1) и легко фиксилось программно, но в случаях задержки более 12 тактов - были сбои. DMA с наивысшим приоритетом и использовался только канал SPI_TX. Недано на скорую руку делал титровалку (наложение текста на видеосигнал) на STM32F373 при скорости SPI близкой к частоте ядра опять те же проблемы. Увеличил BR для SPI (да горизонтальное разрешение упало, но мне не критично) и артефакты пропали. Добавлено: Да, совсем забыл - очень помогает уйти от 8 битных посылок SPI к 16 битным. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KnightIgor 2 15 сентября, 2013 Опубликовано 15 сентября, 2013 · Жалоба Я для приема по spi через dma просто перевожу spi в режим приемника. тогда на sclk spi идут постоянные клоки. Соответственно нет необходимости в передаче по spi. Здесь в какой то ветке про это писали. По завершению приема надо spi переводить в режим приемо-передатчика. Возникает, однако, вопрос, как остановить вовремя прием? Рекомендация на стр. 693 " Then wait for one SPI clock cycle (using a software loop) before disabling the SPI (SPE=0)" в части программной задержки звучит вообще просто дико для системы со множеством прерываний и DMA... Добавлено: Да, совсем забыл - очень помогает уйти от 8 битных посылок SPI к 16 битным. Мне не поможет, т.к. количество байт для считывания может быть и нечетным. P.S. как я и намеревался, замутил тему с передачей одного байта, а затем перегрузку N-1 байтов. Похоже, проблема ушла. Предложение _Pasha толкнуть процесс первый раз синхронно также очень удачен и прост - удивляюсь, как это не пришло в голову мне самому... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexdos 0 15 сентября, 2013 Опубликовано 15 сентября, 2013 · Жалоба Делал светодиодное табло с динамической индикацией: видеопамять с помощью таймеров (каскадное соединение), А это как, на таймерах видеопамять ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nx6310 0 15 сентября, 2013 Опубликовано 15 сентября, 2013 · Жалоба Я останавливаю прием в прерывании от dma. RCC->AHBENR |=RCC_AHBENR_DMA1EN; DMA1_Channel4->CNDTR=size; DMA1_Channel4->CPAR=&spi->DR; DMA1_Channel4->CMAR=RxData; DMA1_Channel4->CCR=0x82; DMA1_Channel4->CCR|=0x01; spi->CR1|=SPI_Direction_2Lines_RxOnly;//настройка на прием //прерывание по dma void DMA1_Channel4_IRQHandler(void){ if(DMA1->ISR&DMA1_FLAG_TC4){ spi->CR1&=~SPI_Direction_2Lines_RxOnly; // отключение режима приемника DMA1->IFCR|=DMA1_FLAG_TC4; DMA1_Channel4->CCR=0x00; RCC->AHBENR &=~RCC_AHBENR_DMA1EN; // spi->CR1&=~0x0040; // spi->CR1 |= 0x0020; // RCC->APB1ENR&=~RCC_APB1ENR_SPI2EN; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KnightIgor 2 15 сентября, 2013 Опубликовано 15 сентября, 2013 · Жалоба Я останавливаю прием в прерывании от dma. А успеет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 15 сентября, 2013 Опубликовано 15 сентября, 2013 · Жалоба Мне не поможет, т.к. количество байт для считывания может быть и нечетным. Почему же? Если данных четное число, то просто отправляем их 16 битными посылками. Если нечетное, то отправляем один байт, дожидаемся приема. Затем отправляем четное количество данных. Ожидание приема можно совместить с настройкой DMA, т.е. отправляете байт, настраиваете DMA, ждете флаг приема (а с учетом Вашей скорости SPI он уже закончится), отправляете данные через DMA 16-битными словами. А это как, на таймерах видеопамять ? Обычно светодиодное табло - это длинный/длинные сдвиговые регистры. В случае динамической индикации все еще интереснее. Так вот, на таймерах STM можно сделать отправку видеоданных через SPI и DMA с формированием всех необходимых строб-сигналов. Т.е. остается только периодически вызывать refresh(), в которой инициализируется таймеры, DMA и SPI - все остальное делается аппаратно, причем не для одной строки, а целиком для всей видеопамяти. Нагрузка на CPU 0%. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nx6310 0 15 сентября, 2013 Опубликовано 15 сентября, 2013 · Жалоба В моем случае глюков не замечалось. обшаюсь через spi с ad7714 и at45db + usb-com. Возможно в ваших условиях и не заработает. Надо проверять/ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 15 сентября, 2013 Опубликовано 15 сентября, 2013 · Жалоба а при 16 битной посылке байты местами поменяются... сам недавно столкнулся и тема на форуме была. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться