Подключаем наши девайсы к компьютеру. Обсуждаются: порты, протоколы, драйвера, языки программирования и т.д.
Ответить

W5500 дробит DHCP пакеты

Ср фев 15, 2023 13:30:55

Добрый день!
Пытаюсь получить динамический IP для своего девайса (STM32 + W5500). Со статическим IP передача данных (UDP сервер и клиент) работают.
А вот реализация DHCP протокола не получается. DHCP_DISCOVER передается в роутер, но по какой то причине полезные данные фрагментированы строго по 2 байта и у каждого пакета свой заголовок вместо одного заголовка и одного пакета данных (около 500Б). Прикладываю картинку как это выглядит в сниффере. Тайминги там тоже какие то странные. И от мк это вряд ли зависит.

Было испробовано:
-отключение прерываний сокета
-изменение размера буфера сокета в W5500 (1 и 2 КБ) В режиме DHCP W5500 настраивается только на сокет 0, а остальные сокеты используются потом при реинициализации (if(dhcpInitFlag == false))
-замена микросхемы W5500 и роутера -без изменений. А так же была попытка использовать пк в качестве DHCP сервера. Что интересно, пк как то умудрялся переварить эти пакеты, но в ответ присылал что-то странное, похожее на оффер, но не совсем по протоколу.

Кончились идеи( Может быть что-то посоветуете? Заранее спасибо

Настройка DHCP сокета:
Код:
Spi2Init();
  // Cброс чипа
//  W5500Disable();
//  HAL_Delay(RESET_DELAY);
  W5500Enable();
  HAL_Delay(RESET_DELAY);
  // Обязательный программный сброс
  W5500WriteByte(W5500_COMMON_REG_BLOCK, W5500_COMMON_REG_MR, COMMON_MR_RST);
  W5500ReadByte(W5500_COMMON_REG_BLOCK, W5500_COMMON_REG_MR);
  // Установка Force ARP
  W5500WriteByte(W5500_COMMON_REG_BLOCK, W5500_COMMON_REG_MR, COMMON_MR_FARP);
  // Установка MAC-адреса
  //memcpy(&NetInfo.mac[0], NetInfo.GetMac(), sizeof(NetInfo.mac));
  FlashReadMacAddress(&NetInfo.devMac[0]);
  W5500WriteBuff(W5500_COMMON_REG_BLOCK, W5500_COMMON_REG_SHAR, &NetInfo.devMac[0], sizeof(NetInfo.devMac));
  // Установка маски подсети
  uint8_t subr[4] = {255,255,255,0};
  ///W5500WriteBuff(W5500_COMMON_REG_BLOCK, W5500_COMMON_REG_SUBR, &NetInfo.sn[0], sizeof(NetInfo.sn));
  W5500WriteBuff(W5500_COMMON_REG_BLOCK, W5500_COMMON_REG_SUBR, &subr[0], sizeof(subr));

  if(dhcpInitFlag == false)
  {
...
  }

  else if(dhcpInitFlag == true)
  {
    uint8_t zeroip[4] = {255,255,255,255};
    W5500WriteBuff(W5500_COMMON_REG_BLOCK, W5500_COMMON_REG_SIPR, &zeroip[0], sizeof(zeroip));
    W5500WriteBuff(W5500_COMMON_REG_BLOCK, W5500_COMMON_REG_GAR,  &zeroip[0], sizeof(zeroip));
    uint8_t intLevel[2] = {0xFF, 0xFE};// 267мкс, t = 4 * (INTLEVEL + 1) / 150MHz
    W5500WriteBuff(W5500_COMMON_REG_BLOCK, W5500_COMMON_REG_INTLEVEL,  &intLevel[0], sizeof(intLevel));
    W5500WriteByte(W5500_COMMON_REG_BLOCK, W5500_COMMON_REG_SIMR, COMMON_SIMR_SN_MASK(DhcpClientSocket));
    W5500WriteByte(W5500_SOCKET_REG_BLOCK(DhcpClientSocket),W5500_SOCKET_REG_IMR, \
        (SOCKET_IMR_SENDOK | /*SOCKET_IMR_TIMEOUT |*/ SOCKET_IMR_RECV /*| SOCKET_IMR_DISCON | SOCKET_IMR_CON*/));
    W5500WriteByte(W5500_SOCKET_REG_BLOCK(DhcpClientSocket), W5500_SOCKET_REG_RXBUF_SIZE, DHCP_CLIENT_SOCKET_SIZE/1024);
    W5500WriteByte(W5500_SOCKET_REG_BLOCK(DhcpClientSocket), W5500_SOCKET_REG_TXBUF_SIZE, DHCP_CLIENT_SOCKET_SIZE/1024);
  }
  // Включение общих прерываний : IP уже есть в сети, IP недопустим
  W5500WriteByte(W5500_COMMON_REG_BLOCK, W5500_COMMON_REG_IMR, \
      (COMMON_IMR_IP_CONFLICT_MASK | COMMON_IMR_IP_UNREACH_MASK));
  // Установка таймаута 200мc
  uint8_t rtr[2] = {0x0F, 0xA0};  // RTR = (tms(400ms) / 1ms) X 10 = 4000(0x0FA0)
  W5500WriteBuff(W5500_COMMON_REG_BLOCK, W5500_COMMON_REG_RTR, &rtr[0], sizeof(rtr));
  // Установка кол-ва повторений после таймаута - 7
  W5500WriteByte(W5500_COMMON_REG_BLOCK, W5500_COMMON_REG_RCR, 0x07);
  // Сброс - включение PHY
  W5500WriteByte(W5500_COMMON_REG_BLOCK, W5500_COMMON_REG_PHYCFGR, COMMON_PHYCFGR_RST);

  NVIC_EnableIRQ(EXTI15_10_IRQn);


Реализация передачи
Код:
bool W5500WriteTxSocket(uint8_t socket, uint8_t* d, uint16_t l)
{
  uint16_t sendLen = l;
  uint16_t socketSize;
  if (socket == TcpClientSocket) socketSize = TCP_CLIENT_SOCKET_SIZE;
  else if (socket == DhcpClientSocket) socketSize = DHCP_CLIENT_SOCKET_SIZE;
  else socketSize = OTHER_SOCKET_SIZE;
  if(sendLen > socketSize)
    return false;
  // ожидание отправки предыдущего пакета
  uint16_t freeSize = 0;
  while(freeSize != socketSize)
  {
    uint8_t fsr[2];
    W5500ReadBuff(W5500_SOCKET_REG_BLOCK(socket), W5500_SOCKET_REG_TX_FSR, &fsr[0], sizeof(fsr));
    W5500ReadBuff(W5500_SOCKET_REG_BLOCK(socket), W5500_SOCKET_REG_TX_FSR, &fsr[0], sizeof(fsr));
    freeSize = (fsr[0] << 8) | fsr[1]; // freeSize = |RD-WR| для UDP или |ACK-WR| для TCP
  }
  // Прочитать указатель в буфере сокета, куда начинать сохранять данные
  uint8_t wr[2];
  W5500ReadBuff(W5500_SOCKET_REG_BLOCK(socket), W5500_SOCKET_REG_TX_WR, &wr[0], sizeof(wr));
  W5500ReadBuff(W5500_SOCKET_REG_BLOCK(socket), W5500_SOCKET_REG_TX_WR, &wr[0], sizeof(wr));
  uint16_t startWriteAdr = (wr[0] << 8) | wr[1];
  // Сохранение данных в буфере сокета
  uint8_t txBuff[3 + sendLen];
  txBuff[0] = wr[0];
  txBuff[1] = wr[1];
  txBuff[2] = (uint8_t) (((W5500_TXBUF_BLOCK(socket) << 3) & 0xF8) | (WRITE_VDM_MODE & 0x07));
  memcpy(&txBuff[3], d, sendLen);
  uint8_t r[sendLen + 3];
  if (false == Spi2Exchg(txBuff, r, sendLen + 3))
    return false;
  // Обновление стартового адреса
  startWriteAdr += sendLen;
  wr[0] = (uint8_t) (startWriteAdr >> 8);
  wr[1] = (uint8_t) startWriteAdr;
  W5500WriteBuff(W5500_SOCKET_REG_BLOCK(socket), W5500_SOCKET_REG_TX_WR, &wr[0], sizeof(wr));
  // Команда на отправку данных из буфера сокета в сеть
  W5500WriteByte(W5500_SOCKET_REG_BLOCK(socket), W5500_SOCKET_REG_CR, SOCKET_COM_SEND);
  //Ожидание выполнения команды
  while(0 != W5500ReadByte(W5500_SOCKET_REG_BLOCK(socket), W5500_SOCKET_REG_CR));
  return true;
}
Вложения
mf.png
(57.71 KiB) Скачиваний: 41

Re: W5500 дробит DHCP пакеты

Ср фев 15, 2023 14:14:35

Видно что маску подсети задали. Но не видно что задаете конкретный IP. И IP днс сервера надо тоже указывать, у вас это роутер. Или я плохо посмотрел...

Re: W5500 дробит DHCP пакеты

Ср фев 15, 2023 14:20:24

Так все эти мероприятия и направлены на то, чтобы получить динамический IP от роутера)

Re: W5500 дробит DHCP пакеты

Ср фев 15, 2023 14:31:52

разве ширпортребные роутеры умеют отдавать джин айпий за натом? их вашето ка раз ставят чтоб девайсвсы к внешке с этой динамикой умели подключатца а сами сидя на статике и да раздача адресоф DHCP это вовсе не динамика по сути после присвоения менятся пара мак-айпи уже не будет пока не пергрузиш роут(некоторые роуты также в энергонезависске сохраняют это тогда и отключени сети не поможет надо стирать в сетапе )

Re: W5500 дробит DHCP пакеты

Ср фев 15, 2023 14:36:47

Так все эти мероприятия и направлены на то, чтобы получить динамический IP от роутера)

А епта) Не правильно понял ваш посыл.

На роутере должен быть включен DHCP

Добавлено after 3 minutes 25 seconds:
разве ширпортребные роутеры умеют отдавать джин айпий за натом?


Почему за натом? Автор подключает сетевую напрямую к роутеру. И роутер должен выдать IP, но для этого на роутере должен быть включен DHCP

Re: W5500 дробит DHCP пакеты

Ср фев 15, 2023 15:58:51

DHCP включен(дал IP адрес на ПК), а WAN я на этом роутере не использую.

Добавлено after 44 minutes 2 seconds:
Я нашла решение, хотя это скорее костыль.
Поменяла номер сокета с нуля на другой и пакеты перестали дробиться, DHCP заработал

Re: W5500 дробит DHCP пакеты

Ср фев 15, 2023 16:03:15

А если уже готовые библиотеки использовать? :)

https://github.com/afiskon/stm32-w5500

Re: W5500 дробит DHCP пакеты

Ср фев 15, 2023 17:27:22

Мне не понравилась реализация.
Да и для понимания процессов лично мне оказалось полезным разобраться в документации и написать самостоятельно.
Но DHCP клиент реализован на основе этой библиотеки, только некоторые методы заменены.
Ответить