Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: SG-DMA в режиме Stream To Memoy
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
Страницы: 1, 2
Acvarif
Спасибо. Примерно так и сделал. Вроде работает. Но с дескрипторами (создаю 2 разных дескриптора с одинаковым количеством буферов) всеравно в каких-то ситуациях выскакивает непонятка.
Подумал может оперировать разными дескрипторами (указателями на разные дескрипторы) некорректно.
Тоесть типа
Код
alt_sgdma_descriptor *receive_descriptors1, *receive_descriptors_copy1;
alt_sgdma_descriptor *receive_descriptors2, *receive_descriptors_copy2;
Можно-ли создать один указатель на дескрипторы (типа alt_sgdma_descriptor *receive_descriptors, *receive_descriptors_copy) (например 2000 буферов(точнее 2000 дескрипторов) по 1152 байта каждый) и разделить это все (условно) на 2 буфера. Потом переключать в прерывании буфера? У меня сомнения по поводу 2000. В регистре control имеются биты MAX_DESC_PROCESSED которые определяют количество заполненных буферов после которых будет сгенерировано прерывание. При инициализации у меня MAX_DESC_PROCESSED = 0х00. Имеею-ли биты MAX_DESC_PROCESSED отношение к моим предполагаемым 2000 буферов?
Хотя наверное это все не прокатит. Как в таком случае сформируется прерывание по заполнению цепочки? Только в конце цепочки. А в этом уже нет смысла.
alexPec

Max_desc_proccessed - это если вам надо прерывание не в конце цепочки, а после какого-то дескриптора, для этого IE_MAX_desc_processed должен быть установлен, иначе фиолетово что там лежит.
Не, схема которую вы предлагаете мутная какая-то. Разберитесь с проблемой раз и навсегда и все. "Запомни лучше день потерять, потом за 5 минут долететь" (С). Для начала определите софт не стартует транзакцию или хард не поставляет данные. Это сигналтапом. И потом, не обратил внимания, щас еще раз перечитал. Не должно быть двух указателей дескрипторов, указывающих на одно место. Т.е. быть то может но ненормально это. Должна отдельная память выделяться. Посмотрите, после транзакции обновляется слово Actual bytes trasferred? Правильное там значение лежит?
Acvarif
Цитата(alexPec @ Oct 4 2012, 23:15) *
Max_desc_proccessed - это если вам надо прерывание не в конце цепочки, а после какого-то дескриптора, для этого IE_MAX_desc_processed должен быть установлен, иначе фиолетово что там лежит.
Не, схема которую вы предлагаете мутная какая-то. Разберитесь с проблемой раз и навсегда и все. "Запомни лучше день потерять, потом за 5 минут долететь" (С). Для начала определите софт не стартует транзакцию или хард не поставляет данные. Это сигналтапом. И потом, не обратил внимания, щас еще раз перечитал. Не должно быть двух указателей дескрипторов, указывающих на одно место. Т.е. быть то может но ненормально это. Должна отдельная память выделяться. Посмотрите, после транзакции обновляется слово Actual bytes trasferred? Правильное там значение лежит?

Спасибо. Понятно.
Начал все с того же - с дескрипторов. После первой транзакции (2 прерывания по заполнению 2_х цепочек дескрипторов (по 8 в каждой цепочке)) (1152 байта каждый дескриптор)
Нажмите для просмотра прикрепленного файлаНажмите для просмотра прикрепленного файла
Напрягает receive_descriptors_copy1 Не допираю откуда там цифра bytes_to_transfer 10112

alexPec
Цитата(Acvarif @ Oct 5 2012, 10:47) *
Спасибо. Понятно.
Начал все с того же - с дескрипторов. После первой транзакции (2 прерывания по заполнению 2_х цепочек дескрипторов (по 8 в каждой цепочке)) (1152 байта каждый дескриптор)
Напрягает receive_descriptors_copy1 Не допираю откуда там цифра bytes_to_transfer 10112

Похоже не заполнен он у вас (не сформирован корректно) - write adr = 0x0. Не должно быть. По шагам формирование проверьте. Если дескриптор этот запускается, то точно зависнет, в 0 писать не правильно.
Acvarif
Цитата(alexPec @ Oct 5 2012, 10:57) *
Похоже не заполнен он у вас (не сформирован корректно) - write adr = 0x0. Не должно быть. По шагам формирование проверьте. Если дескриптор этот запускается, то точно зависнет, в 0 писать не правильно.

С дескрипторами так толком и не понял почему у одной из пар одинаковые адреса и после одного прохода write adr = 0x0.
Но, вобщем и целом механизм вроде работает.
Спасибо.

Немного не понятно по поводу бита PARK в регистре управления.
If the PARK bit is set to 1, the core does not clear the
OWNED_BY_HW bit, thus allowing the same descriptor to be
processed repeatedly without software intervention. You also
need to set the last descriptor in the list to point to the first one.
Почему в прерываниях приходится каждый раз подтверждать 1? Иначе все зависает.
По поводу You also need to set the last descriptor in the list to point to the first one. Насколько это обязательно?
У меня дескрипторы формируются так:
Код
  for(buffer_counter = 0; buffer_counter < number_of_buffers; buffer_counter++)
  {
  temp_length = buffer_length;
    
  receive_ptr = (alt_u32 *)malloc(temp_length);  
  receive_ptr_copy = (alt_u8 *)receive_ptr;
  
  for(contents_counter = 0; contents_counter < temp_length; contents_counter++)
  {
    receive_ptr_copy[contents_counter] = 0;
  }

  alt_avalon_sgdma_construct_stream_to_mem_desc(
                  &receive_descriptors[buffer_counter],  // descriptor
      &receive_descriptors[buffer_counter+1], // next descriptor
      receive_ptr,  // write buffer location
      (alt_u16)temp_length,  // length of the buffer
      0); // writes are not to a fixed location

  }

Подскажите пожалуйста как в этом коде завернуть последний дескриптор на первое место?
alexPec
Цитата
С дескрипторами так толком и не понял почему у одной из пар одинаковые адреса и после одного прохода write adr = 0x0.


Так делов то - если ситуация повторяется, вытащите в сигнал тап write adress и write data у SGDMA для дескрипторов (или у памяти адрес и данные) и триггер на адрес где лежит ваш write_adr, в который ноль пишется - сразу увидите, кто, зачем и после чего пишет туда ноль.

Цитата
Подскажите пожалуйста как в этом коде завернуть последний дескриптор на первое место?


Эээ... А это то вам зачем? Вы же сами буферы меняете и новый дескриптор запускаете после выполнения транзакций. Это как я понял тот случай, когда дма используется, например, для дисплея - там да, чтоб не отвлекать процессор после отображения каждого кадра - завернуть конец на начало и не хай эти дескрипторы крутятся бесконечно, без вмешательства ПО. Один раз запустил - дисплей кажет, меняем только содержимое буферов.
gosu-art
У меня тоже есть вопросики rolleyes.gif
Имею 2 буфера по 8к. весь поток ~64Mбайт(mem to streem). Можно ли зациклить дескрипторы друг на друга? что бы не приходилось лишний раз вызывать alt_avalon_sgdma_do_async_transfer?
alexPec
Цитата(gosu-art @ Nov 19 2012, 13:32) *
У меня тоже есть вопросики rolleyes.gif
Имею 2 буфера по 8к. весь поток ~64Mбайт(mem to streem). Можно ли зациклить дескрипторы друг на друга? что бы не приходилось лишний раз вызывать alt_avalon_sgdma_do_async_transfer?


А чего нет - то? Можно сделать указатель next последнего дескриптора на первый у второго буфера, а у последнего дескриптора первого буфера на первый второго. И вызывать только прерывания, для индикации смены буферов. А конкретно вопрос-то какой?
gosu-art
Т.е. последовательность такая?:
1. Создаю дескрипторы зацикленные друг на друга.
2. Выставляю бит PARK
3. вызываю alt_avalon_sgdma_do_async_transfer и забываю, что у меня есть SGDMA rolleyes.gif
Поток контролируется логикой, прерывание выставляется если будут какие либо ошибки, либо переполнения.

И почему один дескриптор может описать передачу максимум 0xFF00 байт? этот момент я не понял.
alexPec
Цитата(gosu-art @ Nov 20 2012, 10:09) *
Т.е. последовательность такая?:
1. Создаю дескрипторы зацикленные друг на друга.
2. Выставляю бит PARK
3. вызываю alt_avalon_sgdma_do_async_transfer и забываю, что у меня есть SGDMA rolleyes.gif
Поток контролируется логикой, прерывание выставляется если будут какие либо ошибки, либо переполнения.

И почему один дескриптор может описать передачу максимум 0xFF00 байт? этот момент я не понял.


Все вроде верно, не забудьте что бит OWEND_BY_HW во всех дескрипторах должен быть в 1. Повторюсь, что для индикации текущего буфера можно включить прерывания через нцать дескрипторов (видел где-то там такую возможность).

Почему максимум 0xff00? Да ХЗ, не задумывался, может с большими разрядностями счетчиков (а там похоже 16) скорость просаживается, или еще какие проблемы. Вобщем, раз написано так- так и делал.
gosu-art
Цитата(alexPec @ Nov 21 2012, 14:04) *
Почему максимум 0xff00? Да ХЗ, не задумывался, может с большими разрядностями счетчиков (а там похоже 16) скорость просаживается, или еще какие проблемы. Вобщем, раз написано так- так и делал.

Я имел в виду, что в доке такую цифру не нашел rolleyes.gif

Ну вроде начинает получаться:

1. память под дескрипторы и данные

Код
alt_sgdma_descriptor *desc = (alt_sgdma_descriptor *) DESCRIPTOR_MEMORY_BASE;
unsigned char* pkt  = MEM_RX_BASE


2. создаю дескрипторы
Код
alt_avalon_sgdma_register_callback(sgdma_rx_dev,(alt_avalon_sgdma_callback)&tse_sgdmaRx_isr,(alt_u16)ALTERA_AVALON_SGDMA_CONTROL_IE_DESC_COMPLETED_MSK | ALTERA_AVALON_SGDMA_CONTROL_IE_GLOBAL_MSK,sgdma_rx_dev);
    alt_u32 *uncached_packet_payload;
    uncached_packet_payload = pkt; //(void *)alt_remap_cached ((volatile void*) pkt, 4);

    alt_avalon_sgdma_construct_stream_to_mem_desc(
            (alt_sgdma_descriptor *) &desc[ALTERA_TSE_FIRST_RX_SGDMA_DESC_OFST],  // descriptor I want to work with
            (alt_sgdma_descriptor *) &desc[ALTERA_TSE_SECOND_RX_SGDMA_DESC_OFST],  // pointer to "next"
            uncached_packet_payload,            // starting write_address
            0,                                  // read until EOP
            0);
   while ( (IORD_ALTERA_AVALON_SGDMA_STATUS(S_SGDMA_RX_BASE) & ALTERA_AVALON_SGDMA_STATUS_BUSY_MSK) );
    uncached_packet_payload = pkt+(256);

alt_avalon_sgdma_construct_stream_to_mem_desc(
        (alt_sgdma_descriptor *) &desc[ALTERA_TSE_SECOND_RX_SGDMA_DESC_OFST],  // descriptor I want to work with
        (alt_sgdma_descriptor *) &desc[ALTERA_TSE_FIRST_RX_SGDMA_DESC_OFST],  // pointer to "next"
        (uncached_packet_payload),            // starting write_address
        0,                                  // read until EOP
        0);


3. Запускаю последний созданный дескриптор

Код
IOWR_ALTERA_AVALON_SGDMA_CONTROL(S_SGDMA_RX_BASE, ALTERA_AVALON_SGDMA_CONTROL_PARK_MSK);

desc[ALTERA_TSE_FIRST_RX_SGDMA_DESC_OFST].control=128; //выставляю OWNED_BY_HW для первого дескриптора

while ( (IORD_ALTERA_AVALON_SGDMA_STATUS(S_SGDMA_RX_BASE) & ALTERA_AVALON_SGDMA_STATUS_BUSY_MSK) );

alt_avalon_sgdma_do_async_transfer(sgdma_rx_dev, &desc[ALTERA_TSE_SECOND_RX_SGDMA_DESC_OFST]);


условие на прерывание
Код
#define ALTERA_TSE_SGDMA_INTR_MASK              ALTERA_AVALON_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK | ALTERA_AVALON_SGDMA_CONTROL_IE_GLOBAL_MSK |
ALTERA_AVALON_SGDMA_CONTROL_IE_EOP_ENCOUNTERED_MSK |
ALTERA_AVALON_SGDMA_CONTROL_IE_ERROR_MSK |
ALTERA_AVALON_SGDMA_CONTROL_IE_DESC_COMPLETED_MSK


В прерывании проверяю ошибки, статусы. в конце делаю
Код
if(n_desc==0)
     {
         t2=alt_avalon_sgdma_do_async_transfer(sgdma_rx_dev, &desc[ALTERA_TSE_FIRST_RX_SGDMA_DESC_OFST]);
         n_desc=1;
     }
         else
         {

         alt_avalon_sgdma_do_async_transfer(sgdma_rx_dev, &desc[ALTERA_TSE_SECOND_RX_SGDMA_DESC_OFST]);
          n_desc=0;
         }


Все работает. Но мне теперь нужно убрать прерывание и что бы SGDMA молотил поток сам по себе.
Убираю..., в результате выполняется один дескриптор (п.3) и все, дальше ничего crying.gif
Как их зациклить друг на друга в бесконечном цикле?
alexPec
В коде долго разбираться, можете чего-то не заметить, вы посмотрите на результат - найдите адрес дескрипторов (dma->buffer_ptrs->buffer_ptrs[0]->desc_base, если несколько буферов, то у каждого дескрипторы посмотрите). На примере mem to stream (под рукой просто был, Ваш по аналогии) такая картинка должна быть (прил). Зеленый - источник(у вас д.б. ноль, зато получатель - не ноль), синий - след. дескриптор, размер - 0xff00, дальше desc_control, desc_status, actual bytes transferred. Нас интересует в основном desc_control (байт красным выделен) - видно, что ВЕЗДЕ owned by HW равно 1 (старший бит), там в первом дескрипторе 84 - четверка генерирует сигнал SOP, в последнем - 81, однерка генерирует EOP, пусть вас это не смущает, т.е. везде desc_control одинаковый. Отображена память под 5 дескрипторов, последний видно что закольцован на первый. Крутится постоянно, это дма на дисплей, без вмешательства и прерываний, только данные в буфере меняю, они на экране отображаются.

Почему только в первом-то OWNED_BY_HW? Везде поставьте, должно работать

Про 0xff00 - чет сходу тоже не могу найти, когда курил внимательно - точно помню, где-то было сказано.
gosu-art
Цитата(alexPec @ Nov 23 2012, 19:25) *
Почему только в первом-то OWNED_BY_HW? Везде поставьте, должно работать

Т.к. после вызова alt_avalon_sgdma_construct_stream_to_mem_desc он автоматом ставит OWNED_BY_HW, а в предыдущем созданном снимает. Во второй тоже пробовал ставить принудительно - ничего crying.gif
Вот дескрипторы перед запуском:
Нажмите для просмотра прикрепленного файла

Так же как и было - один выполняется на втором виснет:
Нажмите для просмотра прикрепленного файла
Если первым запустить другой дескриптор, то зависает сразу laughing.gif

А теперь самое интересное santa2.gif
Если поставить брэйкпойнт на
Код
alt_avalon_sgdma_do_async_transfer(sgdma_rx_dev, &desc[ALTERA_TSE_SECOND_RX_SGDMA_DESC_OFST]);

а потом "продолжить", то все работает как надо lol.gif
Нажмите для просмотра прикрепленного файла Нажмите для просмотра прикрепленного файла
В чем дело blink.gif ?

alexPec
Чего-то не совсем все ясно, вы, когда дескрипторы уже сформированы, сделайте такой же дамп как я привел, по адресу у вас получается 0x13c40, это ведь первый дескриптор? Ато я вижу bytes to transfer у Вас 0, это же не правильно. Надо в памяти перед запуском смотреть, корка то туда лезет за дескрипторами, а в оболочке ниоса и кривость может какая есть.

И бит OWNED BY HW когда обнуляется, во время создания дескрипторов или после транзакции?
Если во время создания, то подпилите напильником процедуру создания, я тоже так делал, как раз с этим битом что-то такое было.
И с этим do aysnc transfer - он ведь вообще один раз по вашей задумке вызываться должен, если ставим брейк на него, то бесконечно работает дма, не тормозится?
gosu-art
Вот созданные дескрипторы до вызова alt_avalon_sgdma_do_async_transfer(брейкпойнт ща на нем).
Нажмите для просмотра прикрепленного файла
Жмем "Resume" и все работает. alt_avalon_sgdma_do_async_transfer вызывается 1 раз

Теперь перезапускаю систему(в том числе конфигурирую плис) убираю брэйк с async_transfer и ставлю на передаче пакета. После нее, собственно (256 байт), и должен заводится SGDMA_RX.
Выполняю функцию:
Нажмите для просмотра прикрепленного файла
Вроде все норм - 256 байт принял.

После этого снова посылаю пакет 256 байт, но теперь он должен обработаться, по идее, другим дескриптором.
Оправляю...
Нажмите для просмотра прикрепленного файла

И ничего, SGDMA завис crying.gif больше он работать не будет. Сигнал READY не выставляется, еще к тому же левый адрес выставился 0х00011200 а должен быть 0х00011000, но похоже это от предыдущей транзакции.

Может выравнивать чего нужно?
alexPec
Первое что в голову приходит - а почему размер-то передаваемых данных выставлен в ноль (bytes to transfer)?
Может из-за нулевого размера не тормозится трансфер и заезжает на область памяти, где переменные какие-нибудь лежат? Косвенно это подтверждается тем что адрес после трансфера меняется - не должно быть. Попробуйте размер корректный выставить. По вашей картинке значение должно лежать по моему в адресе 0x13818-0x1381B (для первого дескриптора). Дальше думать будем если не пойдет...
gosu-art
Цитата(alexPec @ Nov 26 2012, 17:45) *
Первое что в голову приходит - а почему размер-то передаваемых данных выставлен в ноль (bytes to transfer)?
Может из-за нулевого размера не тормозится трансфер и заезжает на область памяти, где переменные какие-нибудь лежат? Косвенно это подтверждается тем что адрес после трансфера меняется - не должно быть. Попробуйте размер корректный выставить. По вашей картинке значение должно лежать по моему в адресе 0x13818-0x1381B (для первого дескриптора). Дальше думать будем если не пойдет...

Красным я выделил невыполнившийся дескриптор. а ниже со значением 0х100808(запуск начинается с него) это как раз предыдущий, тут все нормально. Что касается с заежанием на область памяти, то я специально сделал отдельную двухпортовую память. Одна сторона SGDMA вторая проц. Даже если превыситься размер буфера, то будет крутится внутри этого порта, только данные испортятся.
Но похоже он next дескиптор не прогружает т.к. сигнал READY не выставляется.
вот как должно быть, это когда с брэйкпойнтом:
Нажмите для просмотра прикрепленного файла
Запись начинается с 0x11100. +256 в конце получаем 0х11200. ready находится в неактивном состоянии (прогружается дескриптор, я так понял) и потом поднимается обратно уже с необходимым следующим адресом 0х11000. Вот так все работает.
Сейчас же если не ставить брэйк то выполнятся 1 дескриптор который вызываю через do_async и на этом все и заканчивается. READY больше не активен после передачи.
Попробую еще в QSYSe собраться 12,1 rolleyes.gif Ща пока в SOPC работаю 11,1
alexPec
И все же, почему количество передаваемых байт в дескрипторе 0? Откуда он берется, не должен быть 0. А в статус-регистре и контрол-регистре после сбоя (когда останавливается ДМА) что лежит? Может ошибка какая, из-за этого и стопорится следующий трансфер? У меня все на Q9.1 сделано.
gosu-art
В общем я тут поковырял alt_avalon_sgdma_construct_stream_to_mem_desc и нашел там такую строчку
Код
IOWR_8DIRECT(&next->control, 0,   (next->control & ~ALTERA_AVALON_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK));

Т.е сброс OWNED_BY_HW у следующего дескриптора. И поэтому когда я создаю четыре дескриптора(для примера) и у последнего указываю next на пустую заглушку. Все 4 выполняются и происходит останов. Если последний указываю на первый, и вызываю alt_avalon_sgdma_do_async_transfer(sgdma_rx_dev, &desc[0]); то транзакции вообще не происходит, а если вызвать второй
alt_avalon_sgdma_do_async_transfer(sgdma_rx_dev, &desc[1]); то выполняются 2,3,4 дескрипторы на первом зависает.
И даже если принудительно поставить desc[0].control=OWNED_BY_HW_MSK; то все равно ничего не проходит. Причем смотрю дамп памяти дескриптора - бит установлен.
В итоге убрал я в этой функции снятие OWNED_BY_HW и все заработало нормально. Но на сколько это правильное решение 1111493779.gif ?
alexPec
Цитата(gosu-art @ Nov 28 2012, 10:50) *
В общем я тут поковырял alt_avalon_sgdma_construct_stream_to_mem_desc и нашел там такую строчку
Код
IOWR_8DIRECT(&next->control, 0,   (next->control & ~ALTERA_AVALON_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK));

Т.е сброс OWNED_BY_HW у следующего дескриптора. И поэтому когда я создаю четыре дескриптора(для примера) и у последнего указываю next на пустую заглушку. Все 4 выполняются и происходит останов. Если последний указываю на первый, и вызываю alt_avalon_sgdma_do_async_transfer(sgdma_rx_dev, &desc[0]); то транзакции вообще не происходит, а если вызвать второй
alt_avalon_sgdma_do_async_transfer(sgdma_rx_dev, &desc[1]); то выполняются 2,3,4 дескрипторы на первом зависает.
И даже если принудительно поставить desc[0].control=OWNED_BY_HW_MSK; то все равно ничего не проходит. Причем смотрю дамп памяти дескриптора - бит установлен.
В итоге убрал я в этой функции снятие OWNED_BY_HW и все заработало нормально. Но на сколько это правильное решение 1111493779.gif ?


Все верно, я об этом и говорил, что во всех дескрипторах в итоге должен стоять в 1 OWNED BY HW. Где ноль - тот не выполняется, транзакция тормозится. Ошибок то при торможении нет? Статусы посмотрите, может тормоз то не из-за дескрипторов возникает, а ошибка какая.

PS Хотя если все работает, то...

bb-offtopic.gif
(С) Папа программист в глубокой отладке... Сын подходит:
-Папа, а почему солнышко встает?
-Встает?
-Да
-Каждый день?
-Да
-И не глючит?
-Нет
-Ради бога ничего не трогай и не меняй!!!
gosu-art
Теперь работает прием и передача (256 байт) без участия проца.
Нажмите для просмотра прикрепленного файла
Поток идет через гигабитный оптический TSE, правда пока передающее буфера статические, не меняют свои значения. Сбои по СRC и переполнениям отсутствуют.
2 alexPec Спасибо за помощь !
Копейкин
Прошу подсказать, где ошибся...
Использую аналогичный SG-DMA stream-to-memory.
QII 9.1sp2
Идея: SG-DMA пишет постоянно из потока в память, дескрипторы (16 шт) закольцованы и нужны прерывания каждые 8 пройденых дескрипторов.
Дескрипторы указывают на память, выделенную под область данных в отправляемых далее пакетах. Т.е. память не сплошная, поэтому 16 дескрипторов, по числу пакетов.
Пока 8 заполняются, 8 передаются. Такой вот пинг-понг...
CODE

int AD7760_prepare_sgdma()
{
ad7760_sgdma = alt_avalon_sgdma_open(SGDMA_1_NAME);

// check
if( ad7760_sgdma == NULL)
{
//TRACE_STR("--> Failed to open SG_DMA_1 Stream-to-memory!\r\n");
return (-1);
}

alt_avalon_sgdma_register_callback(
ad7760_sgdma,
AD7760_callback,
(ALTERA_AVALON_SGDMA_CONTROL_PARK_MSK |
ALTERA_AVALON_SGDMA_CONTROL_IE_GLOBAL_MSK |
ALTERA_AVALON_SGDMA_CONTROL_IE_MAX_DESC_PROCESSED_MSK |
(8<<ALTERA_AVALON_SGDMA_CONTROL_MAX_DESC_PROCESSED_OFST) ),
NULL);

return 0;
}

Дескрипторы:
CODE

void AD7760_prepare_loop_descr_chain()
{
int i;

for( i = 0; i<16; i++ )
{
alt_avalon_sgdma_construct_stream_to_mem_desc(
adchi_desc[i],
(i < 15) ? adchi_desc[i+1] : adchi_desc[0],
(alt_u32*)pFastPacket[i]->data, // Area in external SRAM
FAST_PACKET_BODY_SIZE_BYTES, // in bytes
0 ); // non-fixed write address
}

adchi_desc[0]->control |= ALTERA_AVALON_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK; // Last-first descriptor
}

Стартуем
CODE

void AD7760_start_sgdma()
{
alt_avalon_sgdma_do_async_transfer( ad7760_sgdma, adchi_desc[0] );
}


Функция AD7760_callback() только устанавливает флаги для главного цикла приложения.
Проблема в том, что прерывание приходит, но (судя по времени) когда всё кольцо из 16 дескрипторов выполнится 16 раз.

Сейчас переделал под обработку одного выполненного дескриптора и процессором отсчитываю 8 прерываний, всё работает но некрасиво, самому не нравится.
Где промахнулся,а ???
alexPec
Цитата(Копейкин @ Jan 30 2013, 14:22) *
Где промахнулся,а ???

Прерывание то какое стоит? Судя по вашей задаче должно быть IE_CHAIN_COMPLETED - по завершению цепочки дескрипторов (в вашем случае 2х8). Есть еще IE_DESCRIPTOR_COMPLETED - после каждого дескриптора
Acvarif
Цитата(Копейкин @ Jan 30 2013, 14:22) *
Дескрипторы указывают на память, выделенную под область данных в отправляемых далее пакетах. Т.е. память не сплошная, поэтому 16 дескрипторов, по числу пакетов.
Пока 8 заполняются, 8 передаются. Такой вот пинг-понг...

Если далее отправляются Ethernet пакеты то не нужен пинг-понг и прерывания. Нужно организовать всего-лишь задержку начала передачи пакетов после начала заполнения памяти, тоесть после выполнения команды
Код
alt_avalon_sgdma_do_async_transfer( ad7760_sgdma, adchi_desc[0] );

Все будет крутиться почти одновременно. Единственное, скорость заполнения должна быть в районе скорости передачи. Если это Ethernet 100Base то скорость заполнения должна быть примерно такая-же
Копейкин
Acvarif, там всё сложнее.
DMA заполняет только часть пакета, правда большую, но часть.
Имеется несколько типов пакетов, разной длины, разным адресатам.
Пока заполняются данные 8 пакетов этого АЦП, передаются другие 8 пакетов + еще данные других датчиков.
Поэтому такая система.

Цитата(alexPec @ Jan 30 2013, 18:17) *
Прерывание то какое стоит? Судя по вашей задаче должно быть IE_CHAIN_COMPLETED - по завершению цепочки дескрипторов (в вашем случае 2х8). Есть еще IE_DESCRIPTOR_COMPLETED - после каждого дескриптора


Прерывания по количеству выполненых дескрипторов:

(ALTERA_AVALON_SGDMA_CONTROL_IE_MAX_DESC_PROCESSED_MSK | (8<<ALTERA_AVALON_SGDMA_CONTROL_MAX_DESC_PROCESSED_OFST) )

т.к. строится зацикленная цепочка дескрипторов и бит PARK установлен, т.е. OWNED_BY_HW не чистится...
alexPec
Цитата(Копейкин @ Jan 30 2013, 19:16) *
Прерывания по количеству выполненых дескрипторов:

(ALTERA_AVALON_SGDMA_CONTROL_IE_MAX_DESC_PROCESSED_MSK | (8<<ALTERA_AVALON_SGDMA_CONTROL_MAX_DESC_PROCESSED_OFST) )

т.к. строится зацикленная цепочка дескрипторов и бит PARK установлен, т.е. OWNED_BY_HW не чистится...


Не понял, зачем вам по количеству? Вам же все равно после цепочки вызывать прерывания, так вызовите там do_async_transfer за одно. Циклить то зачем, вызывайте то один то другой.
Копейкин
Мне хотелось по минимуму задействовать процессор, т.к. большой (относительно моей системы) поток данных.
Если иметь прерывание в конце цепочки, то нужно иметь пустой (незадействованный) дескриптор в конце.
Для 2-х цепочек, соответственно 2 пустых дескриптора.
Плюс перезапуск SG-DMA. А так получается замечательно:
1) Цепочка зациклена, перезапуск не требуется
2) Прерывания, в которых только 2 флага (буфер заполнен и верхний/нижний буфер) дёрнуть - минимум операций.

На текущий момент:
1) Зациклить дескрипторы получилось
2) Прерывания по числу дескрипторов приходят не в своё время,
работаю по прерыванию обработки одного дескриптора + подсчёт прерываний.
Копейкин
Посмотрел внимательно на Альтере:
ссылка
там английским языком сказано:
Цитата
Title
Why do I only see one interrupt on the Scatter Gather DMA when enabling the MAX_DESC_PROCESSED interrupt?

Description

If you are using the MAX_DESC_PROCESSED interrupt from the Scatter Gather DMA you must update the MAX_DESC_PROCESSED field at each interrupt to a new value. The core implements an 8 bit counter which automatically wraps to zero when the count value equals 255.

For example, if you wanted the core to generate an interrupt after 2 descriptors were processed continually, you would initially set the MAX_DESC_PROCESSED field to 2 and then upon receiving the first interrupt you would update the MAX_DESC_PROCESSED field to 4, upon receiving the next interrupt update the field to 6 and so on.

Получается нужно обновлять состояние регистра управления на каждом прерывании.
Без вмешательства процессора не обойтись.
А жаль...
alexPec
Цитата(Копейкин @ Jan 31 2013, 16:51) *
Получается нужно обновлять состояние регистра управления на каждом прерывании.
Без вмешательства процессора не обойтись.
А жаль...

Ну да, похоже две цепочки как я говорил проще будут.
Копейкин
Я сейчас, как и описывал, сделал бесконечный цикл по дескрипторам и дескрипторы больше не трогаю.
Прерывание - по обработке одного дескриптора.
В обработчике прерывания считаю количество и устанавливаю флаги.
Мне так проще показалось.
prussta
Добрый день! Хочу запустить SGDMA в режиме mem to srteam. Работаю с отладочной платой DE0 от терасик в Quartus II v.11.1, использую Nios II /e. Было решено запустить альтеровский пример с SGDMA и SSRAM( SSRAM(MM) --> (MM)SGDMA(ST) --> (ST)SGDMA(MM) --> SSRAM(MM)) . Я вместо SSRAM использую SDRAM. Пример запускается, прохожу все шаги до while(tx_done == 0) успешно, но здесь все и заканчивается. То есть я не захожу на свой callback function, где меняю значение tx_done. Почему? ДМА не запускается? или м.б. ошибки при сборки в Qsys? Не могу разобраться. Скриншоты и файлы программы прилагаю.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.