alexPec
Jul 5 2011, 19:04
Добрый день всем. Ситуация такая. Периодически приходят данные, которые отсылаю по dma на выход (мемори то стрим). Данные приходят регулярно, раз в 100 мс. Пока данные копятся в одном буфере, из второго в это время dma качает наружу. Когда проверяю с брейкпоинтами на процедурах старта dma - все стабильно работает. Т.е. нажимаю РАН - останавливается на брейкпоинте старта первого буфера, снова нажимаю РАН - останавливается на брейкпоинте второго буфера и т.д., в таком режиме все ок. Если убираешь брейк хотя бы с одного буфера, т.е. дма запускается два раза без брейка, - все, конец. Больше от ДМА данных не дождешься пока софт не перезапустишь. Признаки такие:
-дескрипторы не портятся, в обоих случаях одинаковые.
Регистры на брейкпоинте:
Статус регистр дма - 0x0000000C ( когда в норме, означает Chain complete + Descriptor complete)
0x00000014 ( когда НЕ в норме, означает Busy + Descriptor complete)
Control регистр дма - 0x00020060 ( когда в норме, означает PARK+RUN+DMAERR) ??? Почему run и dmaerr, ведь транзакция закончена, а dmaerr вообще написано только для stream to memory, а у меня наоборот.
0x00020000 ( когда НЕ в норме, означает PARK)
Порылся в штатных алтеровских процедурах запуска тразакции - поскольку бит busy в 1 - они и не запускают дма. А чем он занят, не понятно. Сигнал дма Ready находится в 1, данные на выход не идут.
UPD: попробовал сделать простую программку, которая по очереди запускает дма сначала первого, потом второго буфера. По шагам все ок, как только запускаешь подряд сначала первый буфер, потом сразу второй - говорит busy и больше не стартует. Как то сбросить бы его...
vadimuzzz
Jul 6 2011, 02:27
проект выложить есть возможность? обрезанный по самое не могу, чтобы только баг воспроизводился
alexPec
Jul 6 2011, 05:19
Цитата(vadimuzzz @ Jul 6 2011, 06:27)

проект выложить есть возможность? обрезанный по самое не могу, чтобы только баг воспроизводился
Нет, проект не могу выложить. Весь весит 800 Мб, урезать - вспотеешь. Да и не факт что баг после урезки проявится.
Вобщем выяснил вот что: если вызываешь функцию alt_avalon_sgdma_do_async_trasfer() до того как заканчивает работу текущий трансфер (dma не закончил передавать, а я начинаю новый трансфер), то все, виснет. Биты бы какие-нибудь у него сбросить, но вроде судя по регистрам нечего...
Ждать бита окончания тоже нельзя, в это время обработка идет. ДМА без прерываний.
vadimuzzz
Jul 6 2011, 05:49
Цитата(alexPec @ Jul 6 2011, 12:19)

ДМА без прерываний.
имеет смысл сделать с прерываниями
alexPec
Jul 11 2011, 06:21
Цитата(vadimuzzz @ Jul 6 2011, 09:49)

имеет смысл сделать с прерываниями
Да там не нужны прерывания, запустил поток - след. запуск гарантированно начинается когда предыдущий закончится (по расчетам). Сейчас беда уже другая. Если один раз построить дескрипторы и запустить - все ок. Если меняешь в дескрипторах чего-нибудь- конец. Опытным путем установлено, что данные вываливаться медленнее начинают. Или цепочка дескрипторов не терминируется как надо.
Такой вопрос появился, из мануала так и не понял точно:
Если запускаем цепочку дескрипторов и в конце этой цепочки надо остановиться (без прерываний, просто стоп), как это указать? Понятно что цепочка - указываем след. дескриптор, а в последнем что меняется? Подозреваю что в регистре Control ДЕСКРИПТОРА бит OWNED BY HARDWARE на это влияет, но как так и не могу понять. Его надо сбросить в последнем дескрипторе или дескрипторе, который следует за последним? Сейчас у меня там (в последнем дескрипторе) число 0x00000080.
vadimuzzz
Jul 11 2011, 11:56
нужно вызвать функцию alt_avalon_sgdma_construct_mem_to_stream_desc((alt_sgdma_descriptor *)desc, (alt_sgdma_descriptor *) next, ...) необходимое число раз (сколько дескрипторов в цепочке). при каждом последующем вызове в качестве параметра desc подставляется next из прошлого вызова. потом alt_avalon_sgdma_do_async_trasfer(). функция alt_avalon_sgdma_construct_mem_to_stream_desc как раз и взводит бит OWNED_BY_HW
alexPec
Jul 15 2011, 09:47
Цитата(vadimuzzz @ Jul 11 2011, 15:56)

нужно вызвать функцию alt_avalon_sgdma_construct_mem_to_stream_desc((alt_sgdma_descriptor *)desc, (alt_sgdma_descriptor *) next, ...) необходимое число раз (сколько дескрипторов в цепочке). при каждом последующем вызове в качестве параметра desc подставляется next из прошлого вызова. потом alt_avalon_sgdma_do_async_trasfer(). функция alt_avalon_sgdma_construct_mem_to_stream_desc как раз и взводит бит OWNED_BY_HW
Это понятно. У меня ДМА запускается разово - запустили, прошел descriptor chain, остановился. Если в descriptor chain последний дескриптор указывает на первый, то он не должен останавливаться... Как он (ДМА) понимает, что дескриптор в descriptor chain последний и что именно после этого дескриптора надо остановиться?
vadimuzzz
Jul 15 2011, 14:41
dma запускается столько раз, сколько была вызвана alt_avalon_sgdma_construct_mem_to_stream_desc. после обработки дескриптора бит OWNED_BY_HW сбрасывается (бит PARK д.б. равен 0). поэтому даже в случае кольцевого списка зацикливания не произойдет. например, пусть будет 2 дескриптора, закольцованных друг на друга. вызываем alt_avalon_sgdma_construct_mem_to_stream_desc 2 раза => будет 2 транзакции
alexPec
Jul 16 2011, 16:32
Цитата(vadimuzzz @ Jul 15 2011, 18:41)

dma запускается столько раз, сколько была вызвана alt_avalon_sgdma_construct_mem_to_stream_desc. после обработки дескриптора бит OWNED_BY_HW сбрасывается (бит PARK д.б. равен 0). поэтому даже в случае кольцевого списка зацикливания не произойдет. например, пусть будет 2 дескриптора, закольцованных друг на друга. вызываем alt_avalon_sgdma_construct_mem_to_stream_desc 2 раза => будет 2 транзакции
Спасибо, ясно.