WIZnet Developer Forum

Need links for DHCP configuration drivers

Hi,

i am trying to get information about DHCP from w5500 datasheet but i didn't find any details. Could you please share links for drivers and reference documents.

See https://old.wiznet.co.kr/sub_modules/en/library/Download_View.asp?PK_Num=95. Very helpful, applies to all WIZnet ethernet chips. For detailed explanation of the DHCP options see here https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol#DHCP_options.

Hello,
i have to the problem with DHCP.
So, I’m implementing ModBus TCP, and I would like to have a DHCP on the board.
I modifieid a little bit the WizNet ioLibrary on SPI read/write functions level, and cannot obtain any result. always timeout.

Here is function sendto

[code]int32_t sendto(SOCKET sn, U8 *buf, U16 len, U8 *addr, U16 port)
{
switch(Read_SOCK_1_Byte(sn, Sn_MR) & 0x0F)
{
case MR_UDP: break;
case MR_MACRAW: break;
default: return SOCKERR_SOCKMODE;
}

do
{
if(len == 0) return SOCKERR_DATALEN;
}while(0);

if(((uint32_t)addr) == 0) return SOCKERR_IPINVALID;
if(port == 0) return SOCKERR_PORTZERO;

U8 tmp = Read_SOCK_1_Byte(sn, Sn_SR);
if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS;

Write_Bytes(Sn_DIPR, addr, 4);
Write_SOCK_2_Byte(sn, Sn_DPORTR, port);
U16 freesize = Read_SOCK_1_Byte(sn, Sn_TXBUF_SIZE);
freesize *= 1024;
if (len > freesize) len = freesize;

while(1)
{
freesize = Read_SOCK_2_Byte(sn, Sn_TX_FSR);
if(Read_SOCK_1_Byte(sn, Sn_SR) == SOCK_CLOSED)
return SOCKERR_SOCKCLOSED;

if(len > freesize) return SOCK_BUSY;
if(len <= freesize) break;

}

Write_SOCK_Data_Buffer(sn, buf, len);

while(Read_SOCK_1_Byte(sn, Sn_CR));

while(1)
{
tmp = Read_SOCK_1_Byte(sn, Sn_IR);
if(tmp == IR_SEND_OK)
{
Write_SOCK_1_Byte(sn, Sn_IR, IR_SEND_OK);
D1printf(“Send OK\n”);
break;
}
else if(tmp == IR_TIMEOUT)
{
Write_SOCK_1_Byte(sn, Sn_IR, IR_TIMEOUT);
D1printf(“Send timeout\n”);
return SOCKERR_TIMEOUT;
}
}

D1printf(“send complete\n”);
return len;
}[/code]

and here is the function wich writes buffer data

[code]// Write data to W5500 Socket data TX Buffer
void Write_SOCK_Data_Buffer(SOCKET s, U8 *dat_ptr, U16 size)
{
U16 offset, offset1;
U16 i;
U8 j;

offset = Read_SOCK_2_Byte(s, Sn_TX_WR);
offset1 = offset;
offset &= (S_TX_SIZE - 1); // Calculate the real physical address

W5500_SCS_LOW;

/* Write Address */
j = SPI_Send(offset/256);
j = SPI_Send(offset);

/* Write Control Byte and read variable size*/
j = SPI_Send(VDM|RWB_WRITE|(s*0x20+0x10));

if((offset + size) < S_TX_SIZE)
{
/* Write Data /
for(i = 0; i < size; i++)
{
/
Send a byte*/
j = SPI_Send(dat_ptr);
dat_ptr++;
}
}
else
{
offset = S_TX_SIZE - offset;
for(i = 0; i < offset; i++)
{
/
Send a byte /
j = SPI_Send(dat_ptr);
dat_ptr++;
}
/
Set W5500 SCS High
/
W5500_SCS_HIGH;

  /* Set W5500 SCS Low */
  W5500_SCS_LOW;

  /* Write Address */
  j = SPI_Send(0x00);
  j = SPI_Send(0x00);

  /* Write Control Byte and read variable size*/
  j = SPI_Send(VDM|RWB_WRITE|(s*0x20+0x10));

  /* Read Data */
  for(;  i< size; i++)
     {
     /* Send a byte */
     j = SPI_Send(*dat_ptr);
     dat_ptr++;
     }
  }

W5500_SCS_HIGH;

/* Updata offset */
offset1 += size;
Write_SOCK_2_Byte(s, Sn_TX_WR, offset1);

/* Write SEND Command */
Write_SOCK_1_Byte(s, Sn_CR, SEND);
}[/code]

The result is:

PLEASE TELL ME WHAT COULD BE THE ERROR

DHCP requests are broadcasts, thus first thing I would start with looking at what is going on on the network using Wireshark. If you will not see any packets W5500 sending, then something wrong in with your design, if it does, then you need to investigate contents of the packet.
In your design “error” could be anywhere. Starting from you setting incorrect MAC address for W5500 to forgetting to initialize source port number.

The hardware is ok 100%.
On the network analyzer a can see:

but i cannot here understand, i’m setting the temporary mac to 00 08 dc 00 00 00, but on the analyzer is 00 08 dc ff ff ff

[code]void DHCP_init(uint8_t s, uint8_t * buf)
{
uint8_t zeroip[4] = {0,0,0,0};

Timer_Configuration();

Read_Bytes(SHAR, DHCP_CHADDR, 6);
if((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00)
{
// Assigning temporary MAC address, you should be set SHAR before call this function.
DHCP_CHADDR[0] = 0x00;
DHCP_CHADDR[1] = 0x08;
DHCP_CHADDR[2] = 0xdc;
DHCP_CHADDR[3] = 0x00;
DHCP_CHADDR[4] = 0x00;
DHCP_CHADDR[5] = 0x00;

  Write_Bytes(SHAR, DHCP_CHADDR, 6);

}
pDHCPMSG = (RIP_MSG*)buf;
DHCP_XID = 0x12345678;

// WIZchip Netinfo Clear
Write_Bytes(GAR, zeroip, 4);
Write_Bytes(SUBR, zeroip, 4);
Write_Bytes(SIPR, zeroip, 4);

reset_DHCP_timeout();
dhcp_state = STATE_DHCP_INIT;

}
[/code]

here is send dhcp discover function:

[code]/* SEND DHCP DISCOVER */
void send_DHCP_DISCOVER(void)
{
uint16_t i;
uint8_t ip[4];
uint16_t k = 0;
makeDHCPMSG();
k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()

// Option Request Param
pDHCPMSG->OPT[k++] = dhcpMessageType;
pDHCPMSG->OPT[k++] = 0x01;
pDHCPMSG->OPT[k++] = DHCP_DISCOVER;

// Client identifier
pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
pDHCPMSG->OPT[k++] = 0x07;
pDHCPMSG->OPT[k++] = 0x01;
pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];

// host name
pDHCPMSG->OPT[k++] = hostName;
pDHCPMSG->OPT[k++] = 0; // fill zero length of hostname
for(i = 0 ; HOST_NAME[i] != 0; i++)
{
pDHCPMSG->OPT[k++] = HOST_NAME[i];
}
pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname

pDHCPMSG->OPT[k++] = dhcpParamRequest;
pDHCPMSG->OPT[k++] = 0x06; // length of request
pDHCPMSG->OPT[k++] = subnetMask;
pDHCPMSG->OPT[k++] = routersOnSubnet;
pDHCPMSG->OPT[k++] = dns;
pDHCPMSG->OPT[k++] = domainName;
pDHCPMSG->OPT[k++] = dhcpT1value;
pDHCPMSG->OPT[k++] = dhcpT2value;
pDHCPMSG->OPT[k++] = endOption;

for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;

// send broadcasting packet
ip[0] = 255;
ip[1] = 255;
ip[2] = 255;
ip[3] = 255;

D1printf("> Send DHCP_DISCOVER\n");
sendto(DHCP_SOCKET, (U8*)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
}[/code]

and here is makeDHCPMSG function

[code]void makeDHCPMSG(void)
{
uint8_t bk_mac[6];
uint8_t* ptmp;
uint8_t i;
Read_Bytes(SHAR, bk_mac, 6);

pDHCPMSG->op = DHCP_BOOTREQUEST;
pDHCPMSG->htype = DHCP_HTYPE10MB;
pDHCPMSG->hlen = DHCP_HLENETHERNET;
pDHCPMSG->hops = DHCP_HOPS;
ptmp = (uint8_t*)(&pDHCPMSG->xid);
*(ptmp+0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24);
*(ptmp+1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16);
*(ptmp+2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8);
(ptmp+3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0);
pDHCPMSG->secs = DHCP_SECS;
ptmp = (uint8_t
)(&pDHCPMSG->flags);
*(ptmp+0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8);
*(ptmp+1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0);

pDHCPMSG->ciaddr[0] = 0;
pDHCPMSG->ciaddr[1] = 0;
pDHCPMSG->ciaddr[2] = 0;
pDHCPMSG->ciaddr[3] = 0;

pDHCPMSG->yiaddr[0] = 0;
pDHCPMSG->yiaddr[1] = 0;
pDHCPMSG->yiaddr[2] = 0;
pDHCPMSG->yiaddr[3] = 0;

pDHCPMSG->siaddr[0] = 0;
pDHCPMSG->siaddr[1] = 0;
pDHCPMSG->siaddr[2] = 0;
pDHCPMSG->siaddr[3] = 0;

pDHCPMSG->giaddr[0] = 0;
pDHCPMSG->giaddr[1] = 0;
pDHCPMSG->giaddr[2] = 0;
pDHCPMSG->giaddr[3] = 0;

pDHCPMSG->chaddr[0] = DHCP_CHADDR[0];
pDHCPMSG->chaddr[1] = DHCP_CHADDR[1];
pDHCPMSG->chaddr[2] = DHCP_CHADDR[2];
pDHCPMSG->chaddr[3] = DHCP_CHADDR[3];
pDHCPMSG->chaddr[4] = DHCP_CHADDR[4];
pDHCPMSG->chaddr[5] = DHCP_CHADDR[5];

for (i = 6; i < 16; i++) pDHCPMSG->chaddr[i] = 0;
for (i = 0; i < 64; i++) pDHCPMSG->sname[i] = 0;
for (i = 0; i < 128; i++) pDHCPMSG->file[i] = 0;

// MAGIC_COOKIE
pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24);
pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16);
pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8);
pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >> 0;
}
[/code]

How do you know that? I did not mean just hardware when talking about “design”. It also includes your routines for chip access (e.g. SPI), and algorithms how you handle communication at W5500 side. Have you been successful in driving W5500 communicating with other UDP devices or TCP devices?

What you see are ARP broadcast requests. Are you sure MAC address is set as you assume? Can you check what SHAR really contains?

Let’s stop focusing on DHCP. You should focus on why W5500 does not send broadcast packets (DHCP is just a subclass of them). Your task is to make it broadcast at least something so that your network analyzer sees it. As soon as analyzer will see broadcast packet, then you can be sure data is sent, and can work on content of communication between W5500 and DHCP server.

For local network broadcast you need to set destination IP address as 255.255.255.255, source port to 68, open UDP socket, set destination port to 67 (DHCP), construct packet (it should contain “broadcast flag” as explained in application note), and send datagram. Make it visible in network analyzer, and then we will see about DHCP handling.

I’m running now ModBusTCP on this hardware with static IP settings:

[code]if(((SETHDATA*)OptionBoardData)->bDHCP == 0)
{
Write_Bytes(GAR, ((SETHDATA*)OptionBoardData)->IpGtw.b, 4);
Write_Bytes(SUBR, ((SETHDATA*)OptionBoardData)->IpSubMsk.b, 4);
Write_Bytes(SHAR, ((SETHDATA*)OptionBoardData)->MacAdr, 6);
Write_Bytes(SIPR, ((SETHDATA*)OptionBoardData)->IpAdr.b, 4);
}
else
{
DHCP_init(DHCP_SOCKET, TX_BUF);
while(1)
{
U8 ret = DHCP_run();

		if(ret == DHCP_IP_LEASED)
		{
			D1printf(" - DHCP Success: DHCP Leased time : %ld Sec.\r\n\r\n", getDHCPLeasetime());
                            result = true;
			break;
		}
		else if(ret == DHCP_FAILED)
		{
			dhcp_retry++;
			if(dhcp_retry <= 3) D1printf(" - DHCP Timeout occurred and retry [%d]\n", dhcp_retry);
		}

		if(dhcp_retry > 3)
		{
			D1printf(" - DHCP Failed\n\n");
			((SETHDATA*)OptionBoardData)->bDHCP = 0;
                            result = false;
			break;
		}
	}
  }

[/code]

I’m reading what i’ve wrote:

[code]void DHCP_init(uint8_t s, uint8_t * buf)
{
U8 zeroip[4] = {0,0,0,0};
U8 tmp_arr[6];

Timer_Configuration();

Read_Bytes(SHAR, DHCP_CHADDR, 6);
if((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00)
{
// Assigning temporary MAC address, you should be set SHAR before call this function.
DHCP_CHADDR[0] = 0x00;
DHCP_CHADDR[1] = 0x08;
DHCP_CHADDR[2] = 0xdc;
DHCP_CHADDR[3] = 0x00;
DHCP_CHADDR[4] = 0x00;
DHCP_CHADDR[5] = 0x00;

  Write_Bytes(SHAR, DHCP_CHADDR, 6);

  Read_Bytes(SHAR, tmp_arr, 6);
  D1printf("tmp_arr = %02x %02x %02x %02x %02x %02x\n",tmp_arr[0],tmp_arr[1],tmp_arr[2],tmp_arr[3],tmp_arr[4],tmp_arr[5]);

}
pDHCPMSG = (RIP_MSG*)buf;
DHCP_XID = 0x12345678;

// WIZchip Netinfo Clear
Write_Bytes(GAR, zeroip, 4);
Write_Bytes(SUBR, zeroip, 4);
Write_Bytes(SIPR, zeroip, 4);

reset_DHCP_timeout();
dhcp_state = STATE_DHCP_INIT;

}
[/code]
and i’m displaing that on terminal:

So, I have setup the analyzer to show me only broadcast frames:

And that means I’m receiving only broadcast messages only from my device.

Please see above function void send_DHCP_DISCOVER(void) and the function sendto(DHCP_SOCKET, (U8*)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT)

I’m setting the socket in UDP mode with source port 68:

[code] // Set Socket n in UDP mode
BOOL Socket_udp(SOCKET s, U16 port)
{
D1printf(“Init UDP socket %i”, s);
Write_SOCK_1_Byte(s, Sn_CR, CLOSE); // Close Socket n
while(Read_SOCK_1_Byte(s, Sn_CR));
Write_SOCK_1_Byte(s, Sn_IR, 0xFF);
while(Read_SOCK_1_Byte(s, Sn_SR) != SOCK_CLOSED);

Write_SOCK_1_Byte(s, Sn_MR, MR_UDP); // Set Socket n in UDP mode

if(!port)
{
port = sock_any_port++;
if(sock_any_port == 0xFFF0)
sock_any_port = SOCK_ANY_PORT_NUM;
}

D1printf(", and port %i\n", port);
Write_SOCK_2_Byte(s, Sn_PORT, port); // set Socket n Port Number
Write_SOCK_1_Byte(s, Sn_CR, OPEN); // Open Socket n

while(Read_SOCK_1_Byte(s, Sn_CR));
while(Read_SOCK_1_Byte(s, Sn_SR) == SOCK_CLOSED);

return true;
}[/code]

the call of this function: Socket_udp(DHCP_SOCKET, DHCP_CLIENT_PORT);

#define DHCP_SERVER_PORT 67 ///< DHCP server port number #define DHCP_CLIENT_PORT 68 ///< DHCP client port number

I’m stuck at the same point as you are.

I had a previous design with W5200, but all drivers made by ourselves.

Now in a new project with W5500, we tried to integrate the ioLibrary into our 8051 code.

Stuck at this point.

But one thing I have tried that isn’t mentioned here is to make sure that SPI comms are working 100% OK.

In my case it took me some time to make read_byte, write_byte, read_burst and write_burst functions to be compatible with my setup.

I would test:

  1. Static IP config, open port and connect with telnet;
  2. Open UDP port and send broadcast.

If you can do these two things, you can find out what’s wrong on your setup by comparing side by side.

[quote=“intellimotion”]
I would test:

  1. Static IP config, open port and connect with telnet;
  2. Open UDP port and send broadcast.
    If you can do these two things, you can find out what’s wrong on your setup by comparing side by side.[/quote]

Thanks for sugestions. I did so and I found my mistake.
I wrote the destination IP in the wrong socket. Now the router answers me, and I hwve now problems with message parsing. I’m still using the ioLibrary from Wiznet. And in the function U8 parseDHCPMSG(void) I have the problem that p is always greater than e, and cannot enter inthe while cycle:

[code]U8 parseDHCPMSG(void)
{
U8 svr_addr[6];
U16 svr_port;
U16 len;
U8* p;
U8* e;
U8 type = 0;
U8 opt_len;

vTaskDelay(100);
len = Read_SOCK_2_Byte(DHCP_SOCKET, Sn_RX_RSR);

if(len > 0)
{
len = recvfrom(DHCP_SOCKET, (U8*)pDHCPMSG, len, svr_addr, &svr_port);
D1printf(“DHCP message : %d.%d.%d.%d(%d) %d received.\n”,svr_addr[0],svr_addr[1],svr_addr[2], svr_addr[3],svr_port, len);
}
else
{
return 0;
}

if (svr_port == DHCP_SERVER_PORT)
{
// compare mac address
if((pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) ||
(pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) ||
(pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5]))
{
return 0;
}

type = 0;
p = (U8 *)(&pDHCPMSG->op);
D1printf(“p = %i\n”, p);
p = p + 240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt)
e = p + (len - 240);

while(p < e)
{
D1printf(“p = %i\n”, p);
switch (*p)
{
case endOption:
p = e; // for break while(p < e)
break;

  case padOption:
    p++;
    break;

  case dhcpMessageType:
    p++;
    p++;
    type = *p++;
    break;

  case subnetMask:
    p++;
    p++;
    DHCP_allocated_sn[0] = *p++;
    DHCP_allocated_sn[1] = *p++;
    DHCP_allocated_sn[2] = *p++;
    DHCP_allocated_sn[3] = *p++;
  break;

  case routersOnSubnet:
    p++;
    opt_len = *p++;       
    DHCP_allocated_gw[0] = *p++;
    DHCP_allocated_gw[1] = *p++;
    DHCP_allocated_gw[2] = *p++;
    DHCP_allocated_gw[3] = *p++;
    p = p + (opt_len - 4);
  break;

  case dns:
    p++;                  
    opt_len = *p++;       
    DHCP_allocated_dns[0] = *p++;
    DHCP_allocated_dns[1] = *p++;
    DHCP_allocated_dns[2] = *p++;
    DHCP_allocated_dns[3] = *p++;
    p = p + (opt_len - 4);
    break;

  case dhcpIPaddrLeaseTime:
    p++;
    opt_len = *p++;
    dhcp_lease_time  = *p++;
    dhcp_lease_time  = (dhcp_lease_time << 8) + *p++;
    dhcp_lease_time  = (dhcp_lease_time << 8) + *p++;
    dhcp_lease_time  = (dhcp_lease_time << 8) + *p++;
    break;

  case dhcpServerIdentifier:
    p++;
    opt_len = *p++;
    DHCP_SIP[0] = *p++;
    DHCP_SIP[1] = *p++;
    DHCP_SIP[2] = *p++;
    DHCP_SIP[3] = *p++;
    break;

  default:
    p++;
    opt_len = *p++;
    p += opt_len;
    break;
  } // switch
} // while

} // if
return type;
}[/code]

Maybe here is the problem with pointers?

Copyright © 2017 WIZnet Co., Ltd. All Rights Reserved.