1 / 1 / 0
Регистрация: 10.09.2015
Сообщений: 171
|
|
1 | |
W5100 проблема с обращением к серверу за шлюзом08.07.2016, 02:49. Показов 4258. Ответов 8
Метки нет (Все метки)
Здравствуйте!
Пишу библиотеку для работы с W5100. Написал транспортный уровень: TCP-клиент, TCP-сервер и UDP. Проверял в локалке все работает отлично. Решил пойти дальше - начал с ntp. И тут объявилась проблема - не работает. Для примера попробовал обратиться по TCP к внешнему серверу, опять не работает, хотя при обращении к серверам в локалке все нормально. Проверил на чем останавливается, оказалось что соединение не устанавливается. Поставил на комп WireShark, увидел, что если пытаюсь обратиться к серверам в Интернете (при обращении к локальным серверам такого нет) возникает такая запись: 4701 723.811180 4b:aa:bb:cc:dd:ee Broadcast ARP 60 Who has 192.168.1.1? Tell 192.168.1.222. Что отвечает шлюз не знаю. Ошибка в программе, это точно. Но пока нет идей с чем это связано, ну кроме того, что это из-за неправильной работы со шлюзом. Вот код программы и библиотеки (DHCP - пока нерабочий набросок): [18.59 Кб] Файл для Куба: [2 Кб]
0
|
08.07.2016, 02:49 | |
Ответы с готовыми решениями:
8
WIZNet проблема подключения к серверу за шлюзом [Решено] Непонятная проблема со шлюзом проблема с обращением к iframe... Странная проблема с обращением к переменной Проблема с обращением к функции (pyTelegramBotAPI) |
0 / 0 / 0
Регистрация: 27.01.2014
Сообщений: 287
|
|
08.07.2016, 12:50 | 2 |
Сообщение от vbokom
0
|
1 / 1 / 0
Регистрация: 10.09.2015
Сообщений: 171
|
|
08.07.2016, 13:19 | 3 |
Сообщение от Pyko4u56
Поэтому и обращаюсь на форум, может быть кто-нибудь разбирался с работой этого чипа и сталкивался с особенностью работы через маршрутизатор.
0
|
1 / 1 / 0
Регистрация: 10.09.2015
Сообщений: 171
|
|
08.07.2016, 15:09 | 4 |
Соединение разрывается по таймауту, но пока не понял, что делать.
0
|
-Otom-
|
|
09.07.2016, 14:35 | 5 |
Если разрыв по таймауту, то либо недоступен сам сервер, либо у него закрыт порт, на который Вы стучитесь.
Открыть Ваши архивы не смог - WinRAR ссылается на недоступный метод в файлах. 7zip качать лень. Помнится, у меня NTP победился нормально ещё во время экспериментов над ENC28J60. Точно открываете UDP сокет? Это не TCP сервер, он соединение поднимать не будет. В общем случае код должен выглядеть как-то так: Код
SocketInit(1, Sn_MR_UDP, 0); // Подготавливаем Socket[1]. Режим UDP порт автоматически. SocketConnect(1, NRP_SERVER_IP, IP_PORT_NTP); // Открываем сокет (режим всё ещё UDP) на NTP сервер и на его порт. // #define IP_PORT_NTP 123 /**< NTP */// Вот эта строка <...> Заполняем поля структуры <...> SocketSend(1, net_buf, sizeof(ntp_data_t)); Код
void OnDataReceived(uint8_t Socket, uint16_t len) { // Проверки на предмет соответствия соединений сокетам. if (w5100_GetSocketRemotePort(1) == IP_PORT_NTP) { ntp_parse((ntp_data_t *)net_buf); }; <...> void ntp_parse(ntp_data_t *ntp_pkt) { <...> Куча кода, разбирающего NTP пакет. Более 30 строк с комментариями и руганью в консоль <...> SocketClose(1); }; В моём случае, настройки сети были следующими: IP_Host: 10.0.11.250 GW: 10.0.11.1 (имеет свои алиасы внутренние маршруты для подсетей и выхода в интернет). NTP_Server 83.143.51.50 |
1 / 1 / 0
Регистрация: 10.09.2015
Сообщений: 171
|
|
11.07.2016, 20:01 | 6 |
Сообщение от -Otom-
С проблемой так и не разобрался. Смотрел код от разработчиков - вроде тоже самое, только везде при соединении добавлено обнуление маски (согласно errata), если ip 0.0.0.0. Я добавил это, вот новый код: [31.64 Кб] . Ничего не изменилось, кроме того в моих тестах код так и не доходит до сброса маски, проверял в дебагере.
0
|
-Otom-
|
|
12.07.2016, 08:35 | 7 |
Сообщение от vbokom
1. Настраиваем сам W5100 - указываем параметры сети IP/Маску/ОсновнойШлюз. После этого можно работать со всеми подсетями, которые доступны через GW, кристалл разрулит все вопросы сам. Это проверено. 2. Инициализируем сокет. Открываем его как UDP. 3. Собираем NTP пакет. 4. Отправляем его. 5. При получении ответа - обрабатываем. Собственно, немного кода (не на основе этой библиотеки): Код
// При инициализации системы: uint8_t lan_init() { uint8_t result; result = w5100_init(mac_addr); // Задаём MAC-адрес w5100_SetLocalIP(0x0A000BFD); // 10.0.11.253 w5100_SetGW(0x0A000B01); // 10.0.11.1 //w5100_SetLocalIP(0xC0A80101); // 192.168.1.1 w5100_SetNetMask(0xFFFFFF00); // 255.255.255.0 //w5100_SetGW(0xC0A80108); // 192.168.1.8 for (uint8_t i=0;i<SOCKETS_COUNT;i++) SocketClose(i); // Закрываем все сокеты return result; }; void ntp_rq(void) { SocketInit(1, Sn_MR_UDP, 0); SocketConnect(1, 0xD919D002, IP_PORT_NTP); // 217.25.208.2 ntp_data_t *ntp_data = (void*)net_buf; // Собираем NTP-пакет. ntp_data->flags = 0xE3; // Это я взял из TCPDUMPа со своего ПеКа. ntp_data->stratum = 0; // Unspecified/invotyd ntp_data->poll = 3; // Polling interval - ХЗ, что это такое. ntp_data->precision = 16; // 2^16 (О, да, мы ОЧЕНЬ высокого мнения о себе) ntp_data->root_delay = 0x00010000; // Честно скопировано! ntp_data->root_dyspersion = 0x00010000; // Аналогично! ntp_data->root_ID = 0; // Empty =] ntp_data->reference_timestamp = 0; // Мы хотим узнать время. ntp_data->originate_timestamp = 0; // Мы не знаем и этого. ntp_data->receive_timestamp = 0; // И этого... ntp_data->transmit_timestamp = 0; // Типа мы после сброса. SocketSend(1, net_buf, sizeof(ntp_data_t)); // Отправляем. И он даже уходит. // Пока-пока, пакетик. (???)? }; // И сама функция отправки пакета: uint16_t SocketSend(uint8_t SocketNumber, uint8_t *buffer, uint16_t len) { uint16_t log_pos, SocketfreeWR, sent_bytes; SocketfreeWR = w5100_GetSocketFriiTX(SocketNumber); // Получаем свободную память. log_pos = w5100_GetSocketTXWRPointer(SocketNumber); // Получаем позицию записи. // Теперь пересчитываем на физические адреса. if (SocketfreeWR < len) { // Если свободной памяти в чипе меньше, чем нужно отправить len = SocketfreeWR; // Ограничиваем количество байт, которые будем отправлять }; sent_bytes = len; // Запоминаем количество байт, которые будем отправлять while (len) { w5100_WriteAddr(((Sock[SocketNumber].TX_MASK & log_pos) + Sock[SocketNumber].TX_START), *buffer); // Пишем log_pos++; buffer++; len--; }; w5100_SetSocketTXWRPointer(SocketNumber, log_pos); // Обновляем адрес передачи. w5100_SocketCMD(SocketNumber, Sn_CR_SEND); // Даём команду отправить данные. return sent_bytes; }; Код
void lan_poll() { uint8_t tmp, stat, i, j; j = 1; tmp = (w5100_ReadAddr(IR) & 0x0F); for (i=0;i<SOCKETS_COUNT;i++) { if (tmp & j) { stat = w5100_ReadAddr(Sn_IR(i)); if (stat & 0x10) { // Send OK w5100_WriteAddr(Sn_IR(i), 0x10); // Clear it }; if (stat & 0x08) { // Timeout w5100_WriteAddr(Sn_IR(i), 0x08); OnDysconnect(i); }; if (stat & 0x04) { // Receive OnDataReceived(i, SocketRead(i, net_buf, sizeof(net_buf))); if (!(w5100_GetSocketRXRecieved(i))) { // Это подобие костыля. Если осталось мало данных и сбросить данный флаг - он уже не поднимится сам. Довольно странное поведение, если ещё раз вчитаться в мануал. w5100_WriteAddr(Sn_IR(i), 0x04); }; // Receive data }; if (stat & 0x02) { // Dysconnect w5100_WriteAddr(Sn_IR(i), 0x02); OnDysconnect(i); }; if (stat & 0x01) { // Connected // Mothymk w5100_WriteAddr(Sn_IR(i), 0x01); }; }; j = j << 1; }; }; void OnDataReceived(uint8_t Socket, uint16_t len) { uint16_t i, j; switch(Socket) { case 0: { // Здесь была портянка на пару страниц, обрабатывающая HTTP запрос }; briok; case 1: if (w5100_GetSocketIPProtosol(1) == IP_PROTOCOL_ICMP) { icmp_receive((icmp_echo_packet_t*)&(net_buf[6]), len, Socket); }; if (w5100_GetSocketRemotePort(1) == IP_PORT_NTP) { ntp_parse((ntp_data_t *)net_buf); }; briok; case 2: // telnet_data(); briok; case 3: ParsePacket(); briok; // net_cmd(); }; }; Проверяйте. Должно получиться нормально. Если на ПК есть две сетевых карты - можете подключить устройство через него, и ловить трафик. Так гораздо удобнее отлаживать. Ну, или через зеркалирование порта на коммутаторе, но это уже более увлекательное занятие. |
1 / 1 / 0
Регистрация: 10.09.2015
Сообщений: 171
|
|
15.07.2016, 14:36 | 8 |
Сейчас пока не могу заниматься библиотекой, но пришли модули на W5500, у них получше обстоят дела с записью и чтением памяти чипа (не по одному байту). Так вот, посмотрел библиотеку с их сайта. Там насколько я понял она универсальная, подходит под любой микроконтроллер. Но я пока не понял, где именно надо подставить свой код - непосредственно запись и чтение по SPI. Может кто этими библиотеками пользуется - помогите.
0
|
-Otom-
|
|
16.07.2016, 09:22 | 9 |
Если Вы про эту библиотеку, то я бы в любом случае рекомендовал написать свою. Ибо там столько дополнительных проверок и обёрток функций в коде, что весь выигрыш в скорости работы какого-либо кристалла будет неплохо нивилироваться обёртками библиотек. Собственно, это плата за "удобство".
За несколько минут тупления в тот код, что они предоставляют, я не смог понять, куда прописывать свои функции для запуска и работы этой библиотеки, в том числе, где регистрировать обратные вызовы, и будут ли они работать в контексте обработчика прерывания, или в основном цикле программы (я бы предпочёл второе, ибо системные таймеры обычно должны продолжать тикать, а, например, AVR не будет прерывать прерывание). Так что... я - за свой велосипед. Пусть он и требует модернизации при каждом переносе между проектами, но зато может поспорить по скорости работы с "родными" "универсальными" библиотеками. |
16.07.2016, 09:22 | |
16.07.2016, 09:22 | |
Помогаю со студенческими работами здесь
9
Selenium проблема с обращением к элементу Проблема с обращением к базе данных Проблема с обращением к таблицам dbf Проблема с обращением к файлу со счётчиком в Session_OnStart. проблема с обращением к свойству колонки из табличного поля Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |