|
|
  |
Ethernet + Cyclone + Nios |
|
|
|
Apr 12 2010, 16:25
|

Участник

Группа: Свой
Сообщений: 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; я прав?
|
|
|
|
|
Apr 12 2010, 22:23
|

Гуру
     
Группа: Свой
Сообщений: 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; скорее всего в обработчике прерывания не запретили прием, а первый пакет еще не разобрали, когда пришел следующий.
|
|
|
|
|
Apr 13 2010, 07:59
|

Участник

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

|
Цитата(vadimuzzz @ Apr 13 2010, 02:38)  скорее всего в обработчике прерывания не запретили прием, а первый пакет еще не разобрали, когда пришел следующий. пока не очень просек как это нужно сделать... но количество заходов в прерывание правильное... отправил 2 пакета, 2 раза и зашел... но принял одинаковый пакет (последний) реально получается что при первом заходе в прерывание в currdescriptor_ptr уже есть первый пакет и вызов функции TseMacReceive(); его затирает...
Сообщение отредактировал wpost - Apr 13 2010, 08:14
|
|
|
|
|
Apr 13 2010, 10:45
|

Участник

Группа: Свой
Сообщений: 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
|
|
|
|
|
Apr 14 2010, 14:35
|

Участник

Группа: Свой
Сообщений: 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) то они будут приниматься нормально без сбоев, но каждый дважды (т.к. он последний в "кучной" транзакции)... где-то лажа... но пока не понятно, где именно...
|
|
|
|
|
Apr 15 2010, 14:14
|

Участник

Группа: Свой
Сообщений: 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
|
|
|
|
|
Apr 15 2010, 15:42
|

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

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

Участник

Группа: Свой
Сообщений: 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....
|
|
|
|
|
Apr 19 2010, 03:57
|
Участник

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

|
Доброе время суток) с TSE начал работать недавно, очень помогла эта тема. Возникло пару вопросов: 1) массив данных находится в памяти(100-500кб), и его надо передат по udp с максимальной скорость, как с минимальной задержкой формировать udp сообщение, имеется ввиду алгоритм, типа сначала десккриптор на заголовок потом на данные и потом уже трансляция в сеть, я правильно мыслю? 2) Как максимально быстро считать контрольную сумму? пробовал через С2H, хороший выйгрыш только на длинных пакетах, также видел в примера встраивание этой функции в sgdma.
|
|
|
|
|
Apr 19 2010, 15:32
|

Участник

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

|
Цитата(vadimuzzz @ Apr 19 2010, 11:40)  ... при помощи DMA скопировать данные из массива в буфер. А у вас случайно нет рабочего примерчика данной операции?
|
|
|
|
|
Apr 19 2010, 22:39
|

Гуру
     
Группа: Свой
Сообщений: 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); } ...
|
|
|
|
|
Apr 20 2010, 08:17
|

Участник

Группа: Свой
Сообщений: 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
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|