Цитата(arhiv6 @ Oct 17 2017, 19:08)

А что вы подразумеваете под "200 нс на настройку DMA"? Это же делается один раз...
А что за микроконтроллер используете?
stm32f407, SCLK 168M
Код
//поток RX
if(DMA_RX_STREAM->CR & DMA_SxCR_EN){
DMA_RX_STREAM->CR &= ~DMA_SxCR_EN;
while(DMA_RX_STREAM->CR & DMA_SxCR_EN){};
}
DMA->DMA_RX_IFCR = DMA_RX_CL_ALL; //очистка всех перываний
DMA_RX_STREAM->M0AR = (uint32_t)pCurrBuffRx;
DMA_RX_STREAM->NDTR = 3;
DMA_RX_STREAM->CR |= DMA_SxCR_EN; //вкл потока
//поток TX
if(DMA_TX_STREAM->CR & DMA_SxCR_EN){
DMA_TX_STREAM->CR &= ~DMA_SxCR_EN;
while(DMA_TX_STREAM->CR & DMA_SxCR_EN){};
}
DMA->DMA_TX_IFCR = DMA_TX_CL_ALL; //очистка всех перываний
DMA_TX_STREAM->M0AR = (uint32_t)&Mem4Tx;
DMA_TX_STREAM->NDTR = 3;
CS_ACTIVE();
DMA_TX_STREAM->CR |= DMA_SxCR_EN; //вкл потока
__ADS_1672_RREF_DMA_TX_STREAM->CR |= DMA_SxCR_EN; //вкл потока
и этот код повторяется 2 раза, т.к. у меня 2 АЦП работают синхронно
Цитата(Lmx2315 @ Oct 17 2017, 22:46)

..если данные постоянно идут - то надо по DMA писать по очереди в два буфера и обрабатывать их по очереди, причём обычно в настройках DMA уже продумано чтобы оно прыгало с одного буфера на другой , что у вас за микроконтроллер?
если бы они шли постоянно, проблем бы не было. Между порциями данный есть пауза, в ней и вся проблема, ее нужно обрабатывать
Цитата(arhiv6 @ Oct 17 2017, 23:18)

Это если настроить DMA в режиме память->память.
Вам нужно после импульса DR прочитать из SPI 4-ре байта в память? Если у вас STM32, попробуйте по прерыванию GPIO ножки, к которой подключен DR запускать чтение по SPI. А DMA настройте на режим периферия->память, с инкрементом указателя памяти и режимом цикличности + работу DMA по событию выставления SPI-ем флага "буфер приёмника не пуст" (RXNE) + включаете прерывания DMA по событию завершения половины обмена и по окончании обмена (HTIE и TCIE). И делайте всю обработку в этих прерываниях, когда в памяти накопится достаточно данных (а буфер можно выделить большой - сколько памяти хватит). Это уже вам сэкономит время.
Не уверен, что так точно можно сделать, но вот как ещё можно доработать: если есть свободный таймер и второй канал DMA то можно не тратить время на обработку прерывания GPIO. Таймер настраиваем на подсчёт импульсов на ножке DR (считать будем до одного, т.е. обрабатывать каждый сигнал DR), этот сигнал запускает второй канал DMA, настроенное в режиме память->периферия для копирования в spi четырёх байт без циклического режима. А так как в SPI при записи происходит одновременно чтение, то получится после импульса DR копирование четырёх байт в память первым каналом DMA. Т.е. контроллер вообще может ничего не делать, только периодически отлавливая прерывания HTIF и TCIF от первого канала DMA.
В любом режиме DMA может работать непрерывно, генерируя запросы к периферии и ожидая от нее готовности данных.
В режиме SPI мастера после настройки и запуска SPI после каждого байта DMA пинает SPI, чтобы тот сгенерировал клок для очередного байта. И пинать будет до тех пор, пока NTDR>0, непрерывно.
Прочитать нужно 3 байта
По поводу прерываний - я так и делаю. EXTI->старт SPI-DMA->прерывание по окончанию транзакции DMA->и к началу. Времени на это не хватает, написал выше
В режиме мастера SPI молотит свой клок без остановки! на какой размер DMA настроили, столько он и зафигачит непрерывным потоком.
Если совсем быть точным, то я настраиваю для SPI и TX и RX. в TX подсовываю 3 пустых байта, как раз для того, чтобы SPI сгенерил клок (ножку TX вообще не настраиваю). А данные снимаю в прерывании rx_transfer_complete.
После окончания приема и до следующего EXTI SPI должен молчать
А вот с таймером мысль интересная, нужно посмотреть его возможности.. но сомневаюсь, что таймер способен запустить чужой DMA. То, что можно через DMA в таймер данные для генерации PWM подсовывать - это да
Еще есть мысль использовать таймер в качестве сигнала CLK. Тогда можно будет настроить DMA и SPI на 100500 байт и запуском/остановкой таймера, то бишь клока регулировать процесс приема данных
Сообщение отредактировал van_de_luxe - Oct 18 2017, 05:42