vadimuzzz 0 12 апреля, 2010 Опубликовано 12 апреля, 2010 · Жалоба я так понимаю что проблема в том, что они диут подряд и новый пакет перекрывает старый при вычитывании из SGDMA не должно такого быть, один дескриптор - один пакет. read until EOP=0 говорит о том, что читать, пока EOP не встретится (длина пакета ведь заранее неизвестна). ненулевое значение в этом поле означает сколько байт читать. надо ловить первое прерывание и разбираться, как дескриптор передали SGDMA, не обработав первый пакет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
wpost 0 12 апреля, 2010 Опубликовано 12 апреля, 2010 · Жалоба не должно такого быть, один дескриптор - один пакет. 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; я прав? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vadimuzzz 0 12 апреля, 2010 Опубликовано 12 апреля, 2010 · Жалоба тут не косяк??? мне что-то подсказывае что должно быть так currdescriptor_ptr = desc+ALTERA_TSE_FIRST_RX_SGDMA_DESC_OFST; я прав? нет, тогда уж currdescriptor_ptr = desc+sizeof(alt_sgdma_descriptor)*ALTERA_TSE_FIRST_RX_SGDMA_DESC_OFST; скорее всего в обработчике прерывания не запретили прием, а первый пакет еще не разобрали, когда пришел следующий. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
wpost 0 13 апреля, 2010 Опубликовано 13 апреля, 2010 (изменено) · Жалоба скорее всего в обработчике прерывания не запретили прием, а первый пакет еще не разобрали, когда пришел следующий. пока не очень просек как это нужно сделать... но количество заходов в прерывание правильное... отправил 2 пакета, 2 раза и зашел... но принял одинаковый пакет (последний) реально получается что при первом заходе в прерывание в currdescriptor_ptr уже есть первый пакет и вызов функции TseMacReceive(); его затирает... Изменено 13 апреля, 2010 пользователем wpost Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
wpost 0 13 апреля, 2010 Опубликовано 13 апреля, 2010 (изменено) · Жалоба Переместил функцию 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; } Изменено 13 апреля, 2010 пользователем wpost Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vadimuzzz 0 14 апреля, 2010 Опубликовано 14 апреля, 2010 · Жалоба это неправильно, порядок должен быть такой: *проверка на ошибки при приеме *обработка пакета (напр., помещение в очередь) *вызов alt_remap_cached и alt_avalon_sgdma_construct_stream_to_mem_desc (подготовка дескрипторов к проведению очередной транзакции) *вызов alt_avalon_sgdma_do_async_transfer (начало асинхронной транзакции) это, что касается обработчика прерывания. в начале работы вызывается read_init, которая делает последние 2 действия. посмотрите код в оригинальном драйвере. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
wpost 0 14 апреля, 2010 Опубликовано 14 апреля, 2010 · Жалоба это неправильно, порядок должен быть такой: *проверка на ошибки при приеме *обработка пакета (напр., помещение в очередь) *вызов 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) то они будут приниматься нормально без сбоев, но каждый дважды (т.к. он последний в "кучной" транзакции)... где-то лажа... но пока не понятно, где именно... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
wpost 0 15 апреля, 2010 Опубликовано 15 апреля, 2010 · Жалоба ладно, отправляем больше пакет (ping -l 20000 -n 1 192.168.0.5) картина: пакеты приходят кучно принимаем 7 пакетов (число всегда постоянное), после 7-ого в прерывание больше не заходит..... Проблема 7-и пакетов решилась очень просто - исправлением ошибки в размере FIFO... он у меня был 2048*32 при необходимых 16384*32 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vadimuzzz 0 15 апреля, 2010 Опубликовано 15 апреля, 2010 · Жалоба что-то непонятно все это. насколько я понимаю, бороться с фрагментацией пакетов дело не драйвера, а IP. для любого драйвера можно подобрать условия, при которых он начнет терять пакеты, это нормальная ситуация, IP учитывает такую возможность. фокусы с "ping -l 20000" на мой взгляд можно рассматривать лишь в роли некоторого стресс-теста, а не как абсолютный показатель (кстати, попробуйте "ping -i 0" + длину побольше). бороться с потерей пакетов путем увеличения буферов, мне кажется, бесперспективно: любой буфер можно зафлудить и переполнить, если обработчик прерывания еле ворочается. так что если хотите расшить узкое место, то начинать надо с прерываний, это известная проблема ниоса. больше интересен факт размножения пакетов. как вы его фиксируете? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
wpost 0 15 апреля, 2010 Опубликовано 15 апреля, 2010 · Жалоба что-то непонятно все это. насколько я понимаю, бороться с фрагментацией пакетов дело не драйвера, а IP. для любого драйвера можно подобрать условия, при которых он начнет терять пакеты, это нормальная ситуация, IP учитывает такую возможность. фокусы с "ping -l 20000" на мой взгляд можно рассматривать лишь в роли некоторого стресс-теста, а не как абсолютный показатель (кстати, попробуйте "ping -i 0" + длину побольше). бороться с потерей пакетов путем увеличения буферов, мне кажется, бесперспективно: любой буфер можно зафлудить и переполнить, если обработчик прерывания еле ворочается. так что если хотите расшить узкое место, то начинать надо с прерываний, это известная проблема ниоса. больше интересен факт размножения пакетов. как вы его фиксируете? Да согласен, обработка прерывания сделана не лучшим образом, медленно ворочается... но пока так... когда более менее отлажусь попробую выйти из положения задав частоту процу 100-150 МГц (сейчас 50) интересный момент, мои BBlaster-ы не хотят заходить в дебаг если я строю ниос систему на частоте более 50. пробовал как LPT blaster, так и USB... итог один не может остановить процессор по ресету... на 50 работают оба программатора нормально... размножение последнего пакета из пачки пакетов замечено при постановке точки останова в прерывание и выводе на консоль идентификатора и смещения пакета. сейчас борюсь простым путем - сравниваю идентификатор и смещение с предыдущим пакетом, при совпадении выхожу из прерывания. так же отмечу, что я вызываю функцию TseMacReceive(); в конце обработки прерывания, а не в начале как вы... таким образом, я не теряю первого пакета из пачки... я думаю тут тесная взаимосвязь. Вы принимали один пакет т.к. ловили всегда второй. попробуйте свой драйвер на прием фрагментированного пинга и вы пропустите пакет со смещением 0.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
d1n1s 0 19 апреля, 2010 Опубликовано 19 апреля, 2010 · Жалоба Доброе время суток) с TSE начал работать недавно, очень помогла эта тема. Возникло пару вопросов: 1) массив данных находится в памяти(100-500кб), и его надо передат по udp с максимальной скорость, как с минимальной задержкой формировать udp сообщение, имеется ввиду алгоритм, типа сначала десккриптор на заголовок потом на данные и потом уже трансляция в сеть, я правильно мыслю? 2) Как максимально быстро считать контрольную сумму? пробовал через С2H, хороший выйгрыш только на длинных пакетах, также видел в примера встраивание этой функции в sgdma. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vadimuzzz 0 19 апреля, 2010 Опубликовано 19 апреля, 2010 · Жалоба и его надо передат по udp с максимальной скорость именно по UDP? на raw ethernet сокетах скорость выше, да и с заголовками возни меньше. по 1) пакет надо передавать TSE целиком, переключать дескриптор с заголовка на данные не получится. напрашивается такой вариант: подготовить буфер, вбить туда заголовок, потом дать смещение и при помощи DMA скопировать данные из массива. после этого пакет можно отдавать в сеть. есть другой вариант: данные в массиве располагать не подряд, а фрагментами, чтобы в свободное место потом вписывать заголовки. тут скорость повыше будет. по 2) максимально быстро сумма считается компонентом с DMA (не sgdma, а именно компонент с Avalon-MM мастером). по идее, туда же можно прикрутить логику для работы с заголовками Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
wpost 0 19 апреля, 2010 Опубликовано 19 апреля, 2010 · Жалоба ... при помощи DMA скопировать данные из массива в буфер. А у вас случайно нет рабочего примерчика данной операции? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vadimuzzz 0 19 апреля, 2010 Опубликовано 19 апреля, 2010 · Жалоба А у вас случайно нет рабочего примерчика данной операции? а чем из примеров в 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); } ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
wpost 0 20 апреля, 2010 Опубликовано 20 апреля, 2010 · Жалоба а чем из примеров в 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться