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

SG-DMA в режиме Stream To Memoy

Дамп - в ниосе window->show view->memory, выбираете адрес начала дескрипторов

Спасибо. С дампом понял.

 

Поскольку возникает ошибка размещения дескрипторов придется возвратиться назад.

Кажется я не до конца понял про формирование дескрипторов.

У меня в функции размещения (взято из примера alteraviki) имеется

// количество буферов
#define NUMBER_OF_BUFFERS 4 
// длина одного буфера
#define BUFFER_LENGTH 1152
// Каждый дескриптор имеет размер в 32 бита
#define ALTERA_AVALON_SGDMA_DESCRIPTOR_SIZE (0x20)
void * temp_ptr_2;
// выделение памяти под дескрипторы = 6 * 32 = 192 бита
temp_ptr_2 = malloc((number_of_buffers + 2) * ALTERA_AVALON_SGDMA_DESCRIPTOR_SIZE);
// инициализация указателя *receive_descriptors_copy - указывает на адрес начала памяти выделенной под дескрипторы
*receive_descriptors_copy = (alt_sgdma_descriptor *)temp_ptr_2;
// инициализация указателя *receive_descriptors - ???
while((((alt_u32)temp_ptr_2) % ALTERA_AVALON_SGDMA_DESCRIPTOR_SIZE) != 0)
{
  temp_ptr_2++;  // slide the pointer until 32 byte boundary is found
}
*receive_descriptors = (alt_sgdma_descriptor *)temp_ptr_2;
// очистка бита OWNED_BY_HW
receive_descriptors[number_of_buffers]->control = 0;

Подскажите пожалуйста почему память под дескрипторы выделяется на 2 больше чем количество буферов.

Не пойму в какое место будет указывать указатель *receive_descriptors?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Написано же :

 

slide the pointer until 32 byte boundary is found.

 

Тут выравнивается начало дескриптора по 32-БАЙТНОЙ границе. Видимо SGDMA так надо, об этом в доке написано что так надо выравнивать. Насчет выделяется больше чем надо - не задумывался, наверно как раз запас на выравнивание по границе...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тут выравнивается начало дескриптора по 32-БАЙТНОЙ границе. Видимо SGDMA так надо, об этом в доке написано что так надо выравнивать. Насчет выделяется больше чем надо - не задумывался, наверно как раз запас на выравнивание по границе...
Понял. Спасибо.

В отладчике после размещения дампы памяти дескрипторов

post-39850-1349159347_thumb.jpg

post-39850-1349159358_thumb.jpg

post-39850-1349159365_thumb.jpg

post-39850-1349159373_thumb.jpg

post-39850-1349159381_thumb.jpg

Как-то странно что 2_ые дескрипторы имеют один и тот же адрес.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все работает. С одним буфером.

С двумя буферами не работает. После заполнения одного буфера

Запускается так:

          if (!(IORD_ALTERA_AVALON_SGDMA_STATUS(SGDMA_0_BASE) & ALTERA_AVALON_SGDMA_STATUS_BUSY_MSK))
            IOWR_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_0_BASE, ALTERA_AVALON_SGDMA_CONTROL_PARK_MSK);

          alt_avalon_sgdma_do_async_transfer(receive_DMA, &receive_descriptors1[0]);

После заполнения первого буфера возникает прерывание в котором делается так:

        while (IORD_ALTERA_AVALON_SGDMA_STATUS(SGDMA_0_BASE) & ALTERA_AVALON_SGDMA_STATUS_BUSY_MSK);
        // Enable SGDMA "parking" mode 
        if (!(IORD_ALTERA_AVALON_SGDMA_STATUS(SGDMA_0_BASE) & ALTERA_AVALON_SGDMA_STATUS_BUSY_MSK))
          IOWR_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_0_BASE, ALTERA_AVALON_SGDMA_CONTROL_PARK_MSK);

        alt_avalon_sgdma_do_async_transfer(receive_DMA, &receive_descriptors2[0]);
..... 
выдача данных из receive_descriptors1 по Ethernet

Тоесть в прерывании запускается прием данных по receive_descriptors2 и начинается выдача накопленных данных по receive_descriptors1

Вроде все должно работать как задумано. Но реально после входа в прерывание и

вызова функции alt_avalon_sgdma_do_async_transfer(receive_DMA, &receive_descriptors1[0]); буфер не переключается.

Посоветуйте пожалуйста куда копать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Честно говоря, не помню из-за чего, 2 года назад было, но сделал у себя так:

unsigned char adc_dma_restart(alt_video_display *display)
{
//    while (IORD_ALTERA_AVALON_SGDMA_STATUS(display->sgdma->base) & ALTERA_AVALON_SGDMA_STATUS_BUSY_MSK);
      /* Enable SGDMA "parking" mode */
    if (!(IORD_ALTERA_AVALON_SGDMA_STATUS(display->sgdma->base) & ALTERA_AVALON_SGDMA_STATUS_BUSY_MSK))
    IOWR_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_0_BASE,
        ALTERA_AVALON_SGDMA_CONTROL_PARK_MSK);

      /* Now start the SGDMA */
return(      alt_avalon_sgdma_do_async_transfer(
        display->sgdma,
        display->buffer_ptrs[display->buffer_being_displayed]->desc_base));
}

Т.е. while закомментил, заменил на условие. Помню, вроде бывало он циклился на while

 

Перезапускаю в прерывании так:

adc_dma->buffer_being_displayed=dmaindex&0x3;//след. буфер и старт транзакции
  dmaindex++;
  adc_dma_restart(adc_dma);

 

Вроде все просто без изысков. Работает стабильно, не виснет долго-долго (дольше суток не проверял). 4 буфера, как видно.

 

А на какой конкретно строчке циклится? Не на while ли? В пошаговом режиме проверте. Уберите для этого оптимизацию кода (в свойствах проекта Nios II Application properties, Optimization level), тогда дебажить будет строго по порядку строчек.

Попробуйте еще вывести в сигнал тап сигналы DMA и проследите, залетает ли в DMA последний байт пакета, меняется ли после последнего байта сигнал ready(софт при этом в пошаговом режиме). Ну а дальше по обстоятельствам...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо. Примерно так и сделал. Вроде работает. Но с дескрипторами (создаю 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 буферов?

Хотя наверное это все не прокатит. Как в таком случае сформируется прерывание по заполнению цепочки? Только в конце цепочки. А в этом уже нет смысла.

Изменено пользователем Acvarif

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

Max_desc_proccessed - это если вам надо прерывание не в конце цепочки, а после какого-то дескриптора, для этого IE_MAX_desc_processed должен быть установлен, иначе фиолетово что там лежит.

Не, схема которую вы предлагаете мутная какая-то. Разберитесь с проблемой раз и навсегда и все. "Запомни лучше день потерять, потом за 5 минут долететь" (С). Для начала определите софт не стартует транзакцию или хард не поставляет данные. Это сигналтапом. И потом, не обратил внимания, щас еще раз перечитал. Не должно быть двух указателей дескрипторов, указывающих на одно место. Т.е. быть то может но ненормально это. Должна отдельная память выделяться. Посмотрите, после транзакции обновляется слово Actual bytes trasferred? Правильное там значение лежит?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Max_desc_proccessed - это если вам надо прерывание не в конце цепочки, а после какого-то дескриптора, для этого IE_MAX_desc_processed должен быть установлен, иначе фиолетово что там лежит.

Не, схема которую вы предлагаете мутная какая-то. Разберитесь с проблемой раз и навсегда и все. "Запомни лучше день потерять, потом за 5 минут долететь" (С). Для начала определите софт не стартует транзакцию или хард не поставляет данные. Это сигналтапом. И потом, не обратил внимания, щас еще раз перечитал. Не должно быть двух указателей дескрипторов, указывающих на одно место. Т.е. быть то может но ненормально это. Должна отдельная память выделяться. Посмотрите, после транзакции обновляется слово Actual bytes trasferred? Правильное там значение лежит?

Спасибо. Понятно.

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

post-39850-1349418569_thumb.jpgpost-39850-1349418685_thumb.jpg

Напрягает receive_descriptors_copy1 Не допираю откуда там цифра bytes_to_transfer 10112

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо. Понятно.

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

Напрягает receive_descriptors_copy1 Не допираю откуда там цифра bytes_to_transfer 10112

Похоже не заполнен он у вас (не сформирован корректно) - write adr = 0x0. Не должно быть. По шагам формирование проверьте. Если дескриптор этот запускается, то точно зависнет, в 0 писать не правильно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Похоже не заполнен он у вас (не сформирован корректно) - 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 

  }

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

Изменено пользователем Acvarif

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

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

 

Эээ... А это то вам зачем? Вы же сами буферы меняете и новый дескриптор запускаете после выполнения транзакций. Это как я понял тот случай, когда дма используется, например, для дисплея - там да, чтоб не отвлекать процессор после отображения каждого кадра - завернуть конец на начало и не хай эти дескрипторы крутятся бесконечно, без вмешательства ПО. Один раз запустил - дисплей кажет, меняем только содержимое буферов.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня тоже есть вопросики :rolleyes:

Имею 2 буфера по 8к. весь поток ~64Mбайт(mem to streem). Можно ли зациклить дескрипторы друг на друга? что бы не приходилось лишний раз вызывать alt_avalon_sgdma_do_async_transfer?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня тоже есть вопросики :rolleyes:

Имею 2 буфера по 8к. весь поток ~64Mбайт(mem to streem). Можно ли зациклить дескрипторы друг на друга? что бы не приходилось лишний раз вызывать alt_avalon_sgdma_do_async_transfer?

 

А чего нет - то? Можно сделать указатель next последнего дескриптора на первый у второго буфера, а у последнего дескриптора первого буфера на первый второго. И вызывать только прерывания, для индикации смены буферов. А конкретно вопрос-то какой?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Т.е. последовательность такая?:

1. Создаю дескрипторы зацикленные друг на друга.

2. Выставляю бит PARK

3. вызываю alt_avalon_sgdma_do_async_transfer и забываю, что у меня есть SGDMA :rolleyes:

Поток контролируется логикой, прерывание выставляется если будут какие либо ошибки, либо переполнения.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Т.е. последовательность такая?:

1. Создаю дескрипторы зацикленные друг на друга.

2. Выставляю бит PARK

3. вызываю alt_avalon_sgdma_do_async_transfer и забываю, что у меня есть SGDMA :rolleyes:

Поток контролируется логикой, прерывание выставляется если будут какие либо ошибки, либо переполнения.

 

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

 

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

 

Почему максимум 0xff00? Да ХЗ, не задумывался, может с большими разрядностями счетчиков (а там похоже 16) скорость просаживается, или еще какие проблемы. Вобщем, раз написано так- так и делал.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...