реклама на сайте
подробности

 
 
26 страниц V  « < 10 11 12 13 14 > »   
Reply to this topicStart new topic
> Ethernet + Cyclone + Nios
vadimuzzz
сообщение Apr 12 2010, 15:41
Сообщение #166


Гуру
******

Группа: Свой
Сообщений: 2 291
Регистрация: 21-07-05
Пользователь №: 6 988



Цитата
я так понимаю что проблема в том, что они диут подряд и новый пакет перекрывает старый при вычитывании из SGDMA

не должно такого быть, один дескриптор - один пакет. read until EOP=0 говорит о том, что читать, пока EOP не встретится (длина пакета ведь заранее неизвестна). ненулевое значение в этом поле означает сколько байт читать. надо ловить первое прерывание и разбираться, как дескриптор передали SGDMA, не обработав первый пакет.
Go to the top of the page
 
+Quote Post
wpost
сообщение Apr 12 2010, 16:25
Сообщение #167


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 1-04-10
Из: СПб
Пользователь №: 56 354



Цитата(vadimuzzz @ Apr 12 2010, 19:56) *
не должно такого быть, один дескриптор - один пакет. read until EOP=0 говорит о том, что читать, пока EOP не встретится (длина пакета ведь заранее неизвестна). ненулевое значение в этом поле означает сколько байт читать. надо ловить первое прерывание и разбираться, как дескриптор передали SGDMA, не обработав первый пакет.


понятно.

тогда есть такой вопрос
при вот таком описании
Код
alt_sgdma_descriptor *desc = (alt_sgdma_descriptor *) ONCHIP_MEMORY2_1_BASE;
alt_sgdma_descriptor *currdescriptor_ptr;

идет обращение
Код
currdescriptor_ptr =  &desc[ALTERA_TSE_FIRST_RX_SGDMA_DESC_OFST];

тут не косяк??? мне что-то подсказывае что должно быть так
Код
currdescriptor_ptr =  desc+ALTERA_TSE_FIRST_RX_SGDMA_DESC_OFST;

я прав?
Go to the top of the page
 
+Quote Post
vadimuzzz
сообщение Apr 12 2010, 22:23
Сообщение #168


Гуру
******

Группа: Свой
Сообщений: 2 291
Регистрация: 21-07-05
Пользователь №: 6 988



Цитата(wpost @ Apr 12 2010, 23:40) *
тут не косяк??? мне что-то подсказывае что должно быть так
Код
currdescriptor_ptr =  desc+ALTERA_TSE_FIRST_RX_SGDMA_DESC_OFST;

я прав?

нет, тогда уж
Код
currdescriptor_ptr =  desc+sizeof(alt_sgdma_descriptor)*ALTERA_TSE_FIRST_RX_SGDMA_DESC_OFST;

скорее всего в обработчике прерывания не запретили прием, а первый пакет еще не разобрали, когда пришел следующий.
Go to the top of the page
 
+Quote Post
wpost
сообщение Apr 13 2010, 07:59
Сообщение #169


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 1-04-10
Из: СПб
Пользователь №: 56 354



Цитата(vadimuzzz @ Apr 13 2010, 02:38) *
скорее всего в обработчике прерывания не запретили прием, а первый пакет еще не разобрали, когда пришел следующий.


пока не очень просек как это нужно сделать...
но количество заходов в прерывание правильное... отправил 2 пакета, 2 раза и зашел... но принял одинаковый пакет (последний)

реально получается что при первом заходе в прерывание в currdescriptor_ptr уже есть первый пакет и вызов функции TseMacReceive(); его затирает...

Сообщение отредактировал wpost - Apr 13 2010, 08:14
Go to the top of the page
 
+Quote Post
wpost
сообщение Apr 13 2010, 10:45
Сообщение #170


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 1-04-10
Из: СПб
Пользователь №: 56 354



Переместил функцию TseMacReceive(); из начала обработки прерывания в конец => просерать пакеты перестало, но выяснился новый баг - последний пакет принимается дважды

Код
void TseMacSgDmaReadInit()
{
    alt_u32 *uncached_packet_payload;
    uncached_packet_payload = (void *)alt_remap_cached ((volatile void*) rx_pkt, 4);
    
    currdescriptor_ptr =  &desc[ALTERA_TSE_FIRST_RX_SGDMA_DESC_OFST];
    nextdescriptor_ptr = (alt_sgdma_descriptor *) IORD_ALTERA_TSE_SGDMA_DESC_NEXT(currdescriptor_ptr);
    blockdescriptor_ptr = currdescriptor_ptr;
    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,            // pkt_array[chain_loop]->nb_buff,                     // starting write_address
            0,                                  // read until EOP
            0);
  
    currdescriptor_ptr =  &desc[ALTERA_TSE_FIRST_RX_SGDMA_DESC_OFST];
    nextdescriptor_ptr = (alt_sgdma_descriptor *) IORD_ALTERA_TSE_SGDMA_DESC_NEXT(currdescriptor_ptr);
    
    int desc_status = 1;
    desc_status = alt_avalon_sgdma_check_descriptor_status(currdescriptor_ptr);
    desc_status = alt_avalon_sgdma_check_descriptor_status(nextdescriptor_ptr);  
    desc_pointer = currdescriptor_ptr;
    
    TseMacRxRead(currdescriptor_ptr);
    
    alt_u32 sgdma_control_rx = 0;
    sgdma_control_rx = IORD_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_1_BASE);
    alt_u32 sgdma_status_rx = 0;
    sgdma_status_rx = IORD_ALTERA_AVALON_SGDMA_STATUS(SGDMA_1_BASE);
}

int TseMacReceive(){
    alt_u32 *uncached_packet_payload;
    alt_u8 tempVar;
    desc_pointer = currdescriptor_ptr;
    alt_u32 desc_stat=0;
    desc_stat = IORD_ALTERA_TSE_SGDMA_DESC_STATUS(desc_pointer);
    
    if ((desc_stat & ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_TERMINATED_BY_EOP_MSK) )
    {
        desc_pointer->status&=~ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_TERMINATED_BY_EOP_MSK;
        nextdescriptor_ptr = (alt_sgdma_descriptor *)IORD_ALTERA_TSE_SGDMA_DESC_NEXT(desc_pointer);
    
        uncached_packet_payload = (void *)alt_remap_cached ((volatile void*) rx_pkt, 4);
       tempVar = IORD_8DIRECT(&nextdescriptor_ptr->control, 0 );
    
        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);                                 // don't write to constant address
        
        IOWR_8DIRECT(&nextdescriptor_ptr->control, 0, tempVar);
        
      //  desc_pointer = nextdescriptor_ptr;
            }
    return 1;
}

alt_u32  TseMacRxRead(alt_sgdma_descriptor *rxDesc)
{
    
    alt_u32 sgdma_status_rx = 0;
    sgdma_status_rx = IORD_ALTERA_AVALON_SGDMA_STATUS(SGDMA_1_BASE);
    alt_u32 sgdma_control_rx = 0;
    sgdma_control_rx = IORD_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_1_BASE);
    
    alt_u8 result = 0;
    while ( (IORD_ALTERA_AVALON_SGDMA_STATUS(SGDMA_1_BASE) & ALTERA_AVALON_SGDMA_STATUS_BUSY_MSK) ){
    }
    result = alt_avalon_sgdma_do_async_transfer(sgdma_rx_dev, (alt_sgdma_descriptor *) rxDesc /*&rxDesc[0]*/);
    

        
return 0;
}


int TseMacSgDmaRxIsr(void * context, alt_u32 id)
{
    alt_u32 rx_section = 0;
    rx_section = IORD_ALTERA_TSEMAC_RX_SECTION_EMPTY(sgdma_rx_dev);
    rx_section = IORD_ALTERA_TSEMAC_CMD_CONFIG(TRIPLE_SPEED_ETHERNET_0_BASE);
    
          //TseMacReceive();    
    IOWR_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_1_BASE, 0x00);
    IOWR_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_1_BASE, ALTERA_TSE_SGDMA_INTR_MASK);

        
    if((IORD_ALTERA_AVALON_SGDMA_STATUS(SGDMA_1_BASE) & ALTERA_AVALON_SGDMA_STATUS_CHAIN_COMPLETED_MSK )){
       TseMacRxRead(currdescriptor_ptr/*desc*/);
    }    
    
    IOWR_ALTERA_AVALON_SGDMA_STATUS(SGDMA_1_BASE,0xFF);
    
       // тут у меня обработка принятого пакета  &rx_pkt[0]

     TseMacReceive();                
return 0;
}


Сообщение отредактировал wpost - Apr 13 2010, 10:50
Go to the top of the page
 
+Quote Post
vadimuzzz
сообщение Apr 14 2010, 03:10
Сообщение #171


Гуру
******

Группа: Свой
Сообщений: 2 291
Регистрация: 21-07-05
Пользователь №: 6 988



это неправильно, порядок должен быть такой:
*проверка на ошибки при приеме
*обработка пакета (напр., помещение в очередь)
*вызов alt_remap_cached и alt_avalon_sgdma_construct_stream_to_mem_desc (подготовка дескрипторов к проведению очередной транзакции)
*вызов alt_avalon_sgdma_do_async_transfer (начало асинхронной транзакции)

это, что касается обработчика прерывания. в начале работы вызывается read_init, которая делает последние 2 действия. посмотрите код в оригинальном драйвере.
Go to the top of the page
 
+Quote Post
wpost
сообщение Apr 14 2010, 14:35
Сообщение #172


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 1-04-10
Из: СПб
Пользователь №: 56 354



Цитата(vadimuzzz @ Apr 14 2010, 07:25) *
это неправильно, порядок должен быть такой:
*проверка на ошибки при приеме
*обработка пакета (напр., помещение в очередь)
*вызов alt_remap_cached и alt_avalon_sgdma_construct_stream_to_mem_desc (подготовка дескрипторов к проведению очередной транзакции)
*вызов alt_avalon_sgdma_do_async_transfer (начало асинхронной транзакции)

это, что касается обработчика прерывания. в начале работы вызывается read_init, которая делает последние 2 действия. посмотрите код в оригинальном драйвере.


Т.е. получается в процедуре read_init
функция alt_remap_cached задает формат работы с памятью (32 разрядные данные),
alt_avalon_sgdma_construct_stream_to_mem_desc указывает SGDMA через какую память и куда копировать,
alt_avalon_sgdma_do_async_transfer взводит SGDMA в ожидание приема.

когда прием закончился, то попадаем в наше прерывание где решаем что делать с принятым пакетом, после чего снова готовим дискриптор (alt_avalon_sgdma_construct_stream_to_mem_desc) и взводим SGDMA на ожидание приема следующего пакета (alt_avalon_sgdma_do_async_transfer).

по факту получается как-то так.

но есть косяк... если отправить фрвгментированный пакет (ping -l 9000 -n 1 192.168.0.5) следующую картину: пакеты приходят кучно принимаем 6 пакетов и после заходим еще раз в прерывание и принимаем повторно 6-ой пакет. на меньшем количестве тоже самое, последнее прерывание - двойное...

ладно, отправляем больше пакет (ping -l 20000 -n 1 192.168.0.5)
картина: пакеты приходят кучно принимаем 7 пакетов (число всегда постоянное), после 7-ого в прерывание больше не заходит.....

Если слать пинги не фрагментированные любой цикличности (ping -n 50 192.168.0.5) то они будут приниматься нормально без сбоев, но каждый дважды (т.к. он последний в "кучной" транзакции)...

где-то лажа... но пока не понятно, где именно...
Go to the top of the page
 
+Quote Post
wpost
сообщение Apr 15 2010, 14:14
Сообщение #173


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 1-04-10
Из: СПб
Пользователь №: 56 354



Цитата(wpost @ Apr 14 2010, 18:50) *
ладно, отправляем больше пакет (ping -l 20000 -n 1 192.168.0.5)
картина: пакеты приходят кучно принимаем 7 пакетов (число всегда постоянное), после 7-ого в прерывание больше не заходит.....


Проблема 7-и пакетов решилась очень просто - исправлением ошибки в размере FIFO... он у меня был 2048*32 при необходимых 16384*32
Go to the top of the page
 
+Quote Post
vadimuzzz
сообщение Apr 15 2010, 15:42
Сообщение #174


Гуру
******

Группа: Свой
Сообщений: 2 291
Регистрация: 21-07-05
Пользователь №: 6 988



что-то непонятно все это. насколько я понимаю, бороться с фрагментацией пакетов дело не драйвера, а IP. для любого драйвера можно подобрать условия, при которых он начнет терять пакеты, это нормальная ситуация, IP учитывает такую возможность. фокусы с "ping -l 20000" на мой взгляд можно рассматривать лишь в роли некоторого стресс-теста, а не как абсолютный показатель (кстати, попробуйте "ping -i 0" + длину побольше). бороться с потерей пакетов путем увеличения буферов, мне кажется, бесперспективно: любой буфер можно зафлудить и переполнить, если обработчик прерывания еле ворочается. так что если хотите расшить узкое место, то начинать надо с прерываний, это известная проблема ниоса. больше интересен факт размножения пакетов. как вы его фиксируете?
Go to the top of the page
 
+Quote Post
wpost
сообщение Apr 15 2010, 18:31
Сообщение #175


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 1-04-10
Из: СПб
Пользователь №: 56 354



Цитата(vadimuzzz @ Apr 15 2010, 19:57) *
что-то непонятно все это. насколько я понимаю, бороться с фрагментацией пакетов дело не драйвера, а IP. для любого драйвера можно подобрать условия, при которых он начнет терять пакеты, это нормальная ситуация, IP учитывает такую возможность. фокусы с "ping -l 20000" на мой взгляд можно рассматривать лишь в роли некоторого стресс-теста, а не как абсолютный показатель (кстати, попробуйте "ping -i 0" + длину побольше). бороться с потерей пакетов путем увеличения буферов, мне кажется, бесперспективно: любой буфер можно зафлудить и переполнить, если обработчик прерывания еле ворочается. так что если хотите расшить узкое место, то начинать надо с прерываний, это известная проблема ниоса. больше интересен факт размножения пакетов. как вы его фиксируете?


Да согласен, обработка прерывания сделана не лучшим образом, медленно ворочается... но пока так... когда более менее отлажусь попробую выйти из положения задав частоту процу 100-150 МГц (сейчас 50)

интересный момент, мои BBlaster-ы не хотят заходить в дебаг если я строю ниос систему на частоте более 50.
пробовал как LPT blaster, так и USB... итог один не может остановить процессор по ресету... на 50 работают оба программатора нормально...

размножение последнего пакета из пачки пакетов замечено при постановке точки останова в прерывание и выводе на консоль идентификатора и смещения пакета. сейчас борюсь простым путем - сравниваю идентификатор и смещение с предыдущим пакетом, при совпадении выхожу из прерывания.

так же отмечу, что я вызываю функцию TseMacReceive(); в конце обработки прерывания, а не в начале как вы... таким образом, я не теряю первого пакета из пачки... я думаю тут тесная взаимосвязь. Вы принимали один пакет т.к. ловили всегда второй. попробуйте свой драйвер на прием фрагментированного пинга и вы пропустите пакет со смещением 0....
Go to the top of the page
 
+Quote Post
d1n1s
сообщение Apr 19 2010, 03:57
Сообщение #176


Участник
*

Группа: Участник
Сообщений: 24
Регистрация: 17-09-08
Пользователь №: 40 261



Доброе время суток)
с TSE начал работать недавно, очень помогла эта тема. Возникло пару вопросов:
1) массив данных находится в памяти(100-500кб), и его надо передат по udp с максимальной скорость, как с минимальной задержкой формировать udp сообщение, имеется ввиду алгоритм, типа сначала десккриптор на заголовок потом на данные и потом уже трансляция в сеть, я правильно мыслю?
2) Как максимально быстро считать контрольную сумму? пробовал через С2H, хороший выйгрыш только на длинных пакетах, также видел в примера встраивание этой функции в sgdma.
Go to the top of the page
 
+Quote Post
vadimuzzz
сообщение Apr 19 2010, 07:25
Сообщение #177


Гуру
******

Группа: Свой
Сообщений: 2 291
Регистрация: 21-07-05
Пользователь №: 6 988



Цитата
и его надо передат по udp с максимальной скорость

именно по UDP? на raw ethernet сокетах скорость выше, да и с заголовками возни меньше.
по 1) пакет надо передавать TSE целиком, переключать дескриптор с заголовка на данные не получится. напрашивается такой вариант: подготовить буфер, вбить туда заголовок, потом дать смещение и при помощи DMA скопировать данные из массива. после этого пакет можно отдавать в сеть. есть другой вариант: данные в массиве располагать не подряд, а фрагментами, чтобы в свободное место потом вписывать заголовки. тут скорость повыше будет.
по 2) максимально быстро сумма считается компонентом с DMA (не sgdma, а именно компонент с Avalon-MM мастером). по идее, туда же можно прикрутить логику для работы с заголовками
Go to the top of the page
 
+Quote Post
wpost
сообщение Apr 19 2010, 15:32
Сообщение #178


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 1-04-10
Из: СПб
Пользователь №: 56 354



Цитата(vadimuzzz @ Apr 19 2010, 11:40) *
... при помощи DMA скопировать данные из массива в буфер.


А у вас случайно нет рабочего примерчика данной операции?
Go to the top of the page
 
+Quote Post
vadimuzzz
сообщение Apr 19 2010, 22:39
Сообщение #179


Гуру
******

Группа: Свой
Сообщений: 2 291
Регистрация: 21-07-05
Пользователь №: 6 988



Цитата(wpost @ Apr 19 2010, 22:47) *
А у вас случайно нет рабочего примерчика данной операции?

а чем из примеров в Software Developer`s Handbok не устраивает?
Код
#include <stdio.h>
#include <stdlib.h>
#include "sys/alt_dma.h"
#include "system.h"
static volatile int rx_done = 0;
/*
* Callback function that obtains notification that the data
* is received.
*/
static void done (void* handle, void* data)
{
    rx_done++;
}
/*
*
*/
int main (int argc, char* argv[], char* envp[])
{
    int rc;
    alt_dma_txchan txchan;
    alt_dma_rxchan rxchan;
    void* tx_data = (void*) 0x901000; /* pointer to data to send */
    void* rx_buffer = (void*) 0x902000; /* pointer to rx buffer */
    /* Create the transmit channel */
    if ((txchan = alt_dma_txchan_open("/dev/dma_0")) == NULL)
    {
        printf ("Failed to open transmit channel\n");
        exit (1);
    }
    /* Create the receive channel */
    if ((rxchan = alt_dma_rxchan_open("/dev/dma_0")) == NULL)
    {
        printf ("Failed to open receive channel\n");
        exit (1);
    }
    /* Post the transmit request */
    if ((rc = alt_dma_txchan_send (txchan,
        tx_data,
        128,
        NULL,
        NULL)) < 0)
    {
        printf ("Failed to post transmit request, reason = %i\n", rc);
        exit (1);
    }
...
Go to the top of the page
 
+Quote Post
wpost
сообщение Apr 20 2010, 08:17
Сообщение #180


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 1-04-10
Из: СПб
Пользователь №: 56 354



Цитата(vadimuzzz @ Apr 20 2010, 02:54) *
а чем из примеров в Software Developer`s Handbok не устраивает?


Да, я тоже думал, что вот оно счастье... но...
к инициализации обоих каналов DMA притензий нет - всё чисто... а вот с приемом и передачей не получается

Код
    int psize = 528; // размер передаваемого массива
    alt_u8 *rx_buf;
    alt_u8 *tx_buf;
   int rc;
    
    

tx_buf = packet+34;  // указатель на место откуда
rx_buf = 34+pkt_pointer+offset; // указатель куда

     if ((rc = alt_dma_txchan_send ( txchan,
                                    tx_buf,
                                    psize,
                                        NULL,
                                        NULL)) < 0)
        {
        printf ("Failed to post transmit request, reason = %i\n", rc);
        exit (1);
        }
      
    if ((rc = alt_dma_rxchan_prepare (  rxchan,
                                       rx_buf,
                                       psize,
                                        done,
                                        NULL)) < 0)
        {
        printf ("Failed to post read request, reason = %i\n", rc); // вот тут вылетаем с кодом -22
        exit (1);
        }
        /* wait for transfer to complete */
        while (!rx_done);
                      #ifdef DEBUG_IP
                      printf ("DMA transfer successful!\n");
                      #endif

Вылетаем на приеме с rc = -22
Go to the top of the page
 
+Quote Post

26 страниц V  « < 10 11 12 13 14 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 10:59
Рейтинг@Mail.ru


Страница сгенерированна за 0.01529 секунд с 7
ELECTRONIX ©2004-2016