billidean
Mar 11 2014, 03:55
Добрый день всем.
На демоплате BeMicro (Cyclone IV E) делаю проект работы с Ethernet (UDP).
При использовании проца Nios II /f все нормально работает. Но для этого проца нужна лицензия (которой у меня нет

).
Попробовал перейти в этом же проекте на Nios II /e, при отправке (из платы) пакетов расчитывается кривая CRC для UDP-заголовка. Для самого тела UDP-пакета можно ставить CRC=0, что я и делаю, а вот для заголовка нужна корректная CRC, иначе прога на ПК вообще не принимает пакет.
Код расчета CRC:
Код
unsigned short checksum(void *b, int len)
{
unsigned short *buf = b, result;
unsigned int sum=0;
for ( sum = 0; len > 1; len -= 2 ) /* Sum all 16b words */
{
// printf("*buf = 0x%x\n", *buf);
sum += *buf++;
}
if ( len == 1 )
/* If any stray bytes, */
sum += *(unsigned char*)buf;
/* add to sum */
sum = (sum >> 16) + (sum & 0xFFFF);
/* Add the carry */
sum += (sum >> 16);
/* (again) */
result = ~sum;
/* Take the one's complement */
return result;
/* Return 16b value */
}
В чем может быть секрет?? Кэшей никаких не использую, поэтому переход на Экономный проц должен вроде пройти без проблем, кроме замедления работы.
Kuzmi4
Mar 11 2014, 07:13
2 billidean
Листинг смотрели ? В IDE отладчике сравнивали результаты на выходе для одинаковых пакетов?
billidean
Mar 11 2014, 07:19
Отладчиком еще не проходился.
Но уже дошел до такого решения. Вечером буду пошагово сравнивать расчет этой CRC для обоих процов.
billidean
Mar 11 2014, 13:52
Дело получилось не таким простым, как показалось мне сначала.
При отладке двух вариантов Nios/e и Nios/f получилось, что сама функция unsigned short checksum(void *b, int len) проводит все операции правильно, а вот данные по адресам void *b получились кривые в случае Nios/e. Формирование этих данных довольно сложное, и поиски "кривых концов" мне не очень улыбаются, поэтому я пока забил на этот вопрос (Но осадок остался).
З.Ы.: Может у кого есть уже наработанное решение (аля "универсальное") подобной проблемы перехода с Fast на Econom Nios ??
Kuzmi4
Mar 11 2014, 14:30
считать в плисе ?
vadimuzzz
Mar 11 2014, 22:59
Цитата(billidean @ Mar 11 2014, 20:52)

При отладке двух вариантов Nios/e и Nios/f получилось, что сама функция unsigned short checksum(void *b, int len) проводит все операции правильно, а вот данные по адресам void *b получились кривые в случае Nios/e.
фокусы с кэшем?
billidean
Mar 12 2014, 01:52
Цитата
считать в плисе ?
Вы имеете в виду вынести формирование пакета за пределы НИОСа во внешний модуль ПЛИС, который наберет все нужные данные из НИОСа и сформирует отправной пакет? Это конечно интересно, и не будет зависеть от НИОСа и его типа, НО большая проблема в том, что кристалл забит почти на 90%. Проект компилится несколько часов с несколькими заходами в фиттеровщик.
В настройках НИОСа кэш данных отключен, с ним даже Фаст проц чота глючил при формировании пакетов.
Могу выложить исходники проекта НИОСа, если будет желание в нем покопаться.
Serhiy_UA
Mar 12 2014, 03:09
Попробуйте создать тестовые примеры, максимально все упростив. Вычисляйте Ниосом только контрольную сумму для одного и того же массива по каждому из вариантов и сравнивайте между собой. Таким способом будет легче найти причину, если причина в этой сумме...
У меня контрольная сумма для UDP вычислялась аппаратно в двух потоках (когда один поток через Ниос передавался, другой аппаратно обсчитывался, и наоборот), что было связано с требованием высокого быстродействия.
billidean
Mar 12 2014, 03:53
Цитата
Вычисляйте Ниосом только контрольную сумму для одного и того же массива по каждому из вариантов и сравнивайте между собой.
В этом то и загвоздка получилась, работа функции расчета CRC корректная, а вот данные для расчета получились неверные при Эконом. процессоре.
Очень затрудняет процесс отладки то, что при использовании Эконом. НИОСа нельзя ставить брейкпойнты, и приходится через printf() все контролировать, а это та еще песня. При выдачи больших объемов вывод ч/з LTAG может зависнуть (несколько раз на такое натыкался) в то время как программа уже ускокала далеко вперед.
Kuzmi4
Mar 12 2014, 06:07
2 billidean
Как это нельзя ставить брейкпойнты? Кто вам это сказал ?
Всё можно, только там SW-breakpoint, но в вашем случае это не сыграет какой то важной роли.
billidean
Mar 12 2014, 06:35
Вроде я такое же читал, что при Эконом.НИОС будут софтовые точки останова. Но когда скомпилил проект к квартусе, затем открыл проект в еклипсе, то сколько бы я не тыкал мышью в разных местах, точки останова не ставились. Может просто глюк был, седня попробую еще раз.
Kuzmi4
Mar 12 2014, 06:43
2 billidean
У меня в проектах обычно Nios2-e, патроны подавать много мозгов не надо, так отладка всегда работает без вопросов (Q2 v9.0sp2 / Q2 v13.0sp1). Даже когда собираю скриптами, потом импортирую проект в эклипс и в уже импортированном выбираю папки/сорцы и в сорцах ставлю точки останова.
Если не получится выставить брейкпойнты, тогда выкладывайте здесь обрезанный вариант - интересно будет глянуть.
Копейкин
Mar 12 2014, 06:44
Если код был "оптимизирован", то там точку останова поставить не даст.
Уровень оптимизации одинаков в обоих случаях? И какой?
billidean
Mar 12 2014, 07:37
настройки BSP в части оптимизации были по умолчанию (о0) в обоих случаях.
Исходники не менял при переходе между процами.
Вечером еще раз попробую погонять, может что прояснится.
billidean
Mar 12 2014, 11:57
Вобщем все вроде заработало.
Дело было в указании адреса на элемент массива подготовленных данных (пакета), начиная с которого необходимо расчитывать контрольную сумму для IP-заголовка. Этот адрес был сдвинут на один байт правее. Но почему в Фаст.НИОСе при этом производился правильный расчет CRC - это пока загадка.
Golikov A.
Mar 12 2014, 14:59
потому что фаст наверняка 32 битный, и при сдвиге на 1 - 2 - 3 байта все равно попадает в 0 байт. А этот почему то честно отработал...
billidean
Mar 13 2014, 00:05
Я тоже так подумал, но вот искать истину пока некогда. Хотя всегда считал, что вне зависимости от типа проца. он всегда 32-хбитный. Надо почитать описание поточнее.
billidean
Mar 13 2014, 06:24
Посмотрел доку "Implementation Details" на НИОС (n2cpu_nii51015.pdf), не нашел про изменение работы с памятью (32-хбитное обращение или 8-мибитное) для разных версий проца.
Kuzmi4
Mar 13 2014, 07:18
2 billidean
вставьте в С-код выравнивание, откоментируйте это и забудьте
Golikov A.
Mar 13 2014, 07:21
а шина везде одна и таже?
Потом в дорогом проце считался могла быть железная, а передача 32 битными словами, а в дешевом считалка программная и доступ 8 битный.
В ксалинксе так, дешевый мак считает суммы алгоритмически, а дорогой железом.
alexadmin
Mar 13 2014, 07:26
Цитата(Golikov A. @ Mar 13 2014, 11:21)

а шина везде одна и таже?
Потом в дорогом проце считался могла быть железная, а передача 32 битными словами, а в дешевом считалка программная и доступ 8 битный.
Нет, базовая архитектура всех ниосов одинакова.
billidean
Mar 13 2014, 07:29
Вот моя структура пакета в .h-файле
Код
typedef struct UDP_str
{
char macDst[6];
char macSrc[6];
char type[2];
char ver_lenIP;
char all00;
char len_28plus[2];
char id_pack[2];
char fl_4000[2];
char time_l_80;
char type_UDP_11;
char crc16_IPhead[2];
char ipSrc[4];
char ipDst[4];
char portSrc[2];
char portDst[2];
char lenUDP_8plus[2];
char crc16_UDP[2];
// до этого ... длина равна 42 байта
char data[UDP_DATA_MAX_SIZE];
} __attribute__((__packed__)) UDP_str;
Вот код в .c-файле
Код
volatile UDP_str udp_send_s __attribute__ ((aligned (1)));
volatile UDP_str udp_take_s __attribute__ ((aligned (1)));
После этого я считаю, что обе структуры выровнено по-байтово и без "дырок" между полями.
Расчет CRC для IP-заголовка должен начинаться с поля ver_lenIP, и просчитывать 20 байт, а я указал (ошибочно), чтобы начинался расчет с поля all00, т.е. сдвинул на один байт вправо. При этом НИОС/Фаст все нормально расчитывал, а вот НИОС/Эконом выдавал кривую CRC, из-за чего я и обнаружил свой косяк в указании начального адреса расчета CRC.
Поэтому и началось обсуждение типов НИОСов и их обращение к памяти.
Golikov A.
Mar 13 2014, 08:22
тогда битность шины не причем, был бы сдвиг в плюс это можно было бы обосновать выравниванием. А сдвиг в минус, никак не объясним...
billidean
Mar 13 2014, 09:39
Если шина 32-хбитная, и мы указываем на 2-ой или 3-тий байт ячейки, то эта ячейка будет задействована полностью, начиная с 1-го байта, т.о. будем иметь сдвиг по адресу влево, в сторону уменьшения.
Если посмотреть на шину Авалон, то эта ситуация очень видна, НО в этой шине все (имею в виду побайтовое обращение) разруливается доп.сигналами byteenable.
Serhiy_UA
Mar 13 2014, 10:14
Цитата(billidean @ Mar 13 2014, 11:29)

Вот моя структура пакета в .h-файле
У меня структура UDP-пакетов несколько схожая, но отличается служебными словами PACKED, у них тоже была своя роль...
//------------------- UDPFRAME
typedef struct udphdr { //8 bytes
u_short uh_sport PACKED; /*!< \brief Source port */
u_short uh_dport PACKED; /*!< \brief Destination port */
u_short uh_ulen PACKED; /*!< \brief UDP length */
u_short uh_sum PACKED; /*!< \brief UDP checksum */
} UDPHDR;
struct UDPFRAME {
ETHERHDR eth_hdr PACKED; //14 bytes
IPHDR ip_hdr PACKED; //20 bytes
UDPHDR udp_hdr PACKED; // 8 bytes
u_char md[1472] PACKED; // + (22..1476) bytes
};
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.