I’m using Wiznet’s ioLibrary to set up DHCP on my W5500. I’ve got an issue with the DHCP code in the ioLibrary - it doesn’t manage to obtain an IP address, and fails after around 30 seconds.
Since I’m using an ATmega32U4, I can upload Arduino Leonardo code too - I’ve verified that the Arduino Ethernet2 DHCP address printer example works and successfully negotiates an IP address, so it’s apparently not a hardware issue.
My code includes two timers: one that triggers every 1s for the DHCP_time_handler()
routine in the ioLibrary DHCP module, and another that triggers every 1s for sensor readings. I’ve verified that both of these timers are actually triggering at these rates. Here it is:
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
// ioLibrary headers
#include <socket.h>
#include <dhcp.h>
// code for SPI communication with W5500
#include "spi.h"
// DHCP data buffer
uint8_t dhcp_buf[2048];
// socket buffer sizes, in kB
uint8_t wiznet_buf_size[] = {2, 2, 2, 2, 2, 2, 2, 2};
// timer overflow counters
uint16_t dhcp_timer_ovf_count = 0;
uint16_t env_timer_ovf_count = 0;
// whether a new measurements have been made
bool env_measurement_ready = false;
// network info (only MAC used by DHCP)
wiz_NetInfo net_info = { .mac = {0x00, 0x08, 0xdc, 0xab, 0xcd, 0xef},
.ip = {192, 168, 0, 101},
.sn = {255, 255, 255, 0},
.gw = {192, 168, 0, 1},
.dns = {0, 0, 0, 0},
.dhcp = NETINFO_DHCP };
void dhcp_timer_enable(void) {
// enable first timer
TIMSK1 |= (1 << TOIE1);
// set initial value to 0
TCNT1 = 0x00;
// start timer with 1/1 scaling
// this gives overflows every (1/16e6)*65536 = 4.096 ms
TCCR1B = (1 << CS01);
}
void sensor_timer_enable(void) {
// enable first timer
TIMSK3 |= (1 << TOIE3);
// set initial value to 0
TCNT3 = 0x00;
// start timer with 1/1 scaling
// this gives overflows every (1/16e6)*65536 = 4.096 ms
TCCR3B = (1 << CS30);
}
// 16-bit TIMER1 for DHCP timing
ISR(TIMER1_OVF_vect) {
dhcp_timer_ovf_count++;
if (dhcp_timer_ovf_count >= 244) {
// trigger every ~1 second
DHCP_time_handler();
dhcp_timer_ovf_count = 0;
}
}
// 16-bit TIMER3 for sensor measurements
ISR(TIMER3_OVF_vect) {
// triggers every 4.096 ms
env_timer_ovf_count++;
// approx 1 second
if (env_timer_ovf_count >= 244) {
// SENSOR MEASUREMENTS MADE HERE
env_measurement_ready = true;
// reset timer
env_timer_ovf_count = 0;
}
}
int main(void) {
bool run_user_applications = false;
hardware_init();
sensor_timer_enable();
// register chip select and SPI callback functions
reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect);
reg_wizchip_spi_cbfunc(spi_receive, spi_send);
// initialise W5500
wizchip_init(wiznet_buf_size, wiznet_buf_size);
wizchip_setnetinfo(&net_info);
// initialise DHCP on socket 0
dhcp_timer_enable();
DHCP_init(0, dhcp_buf);
for (;;) {
switch (DHCP_run()) {
case DHCP_IP_ASSIGN:
usb_send_message("IP assigned\n");
break;
case DHCP_IP_CHANGED:
usb_send_message("IP changed\n");
break;
case DHCP_IP_LEASED:
run_user_applications = true;
break;
case DHCP_FAILED:
usb_send_message("DHCP failed\n");
break;
default:
break;
}
if (run_user_applications) {
if (env_measurement_ready) {
// SENSOR READINGS PRINTED HERE
// reset
env_measurement_ready = false;
}
}
}
}
void hardware_init(void) {
// disable watchdog if enabled by bootloader/fuses
MCUSR &= ~(1 << WDRF);
wdt_disable();
// disable clock division
clock_prescale_set(clock_div_1);
// set W5500 chip select as output
DDRB |= (1 << PORTB6);
// disable W5500 chip select
PORTB |= (1 << PORTB6);
// initialise SPI
spi_init();
}
(I’ve stripped out code for USB virtual serial, SPI chip select and send/receive, etc. to keep the code to a minimum. I’ve left in the timer code in case someone spots an issue with those.)
With that code, nothing happens for around 30 seconds until “DHCP failed” is printed to the USB terminal. This repeats every 30 seconds infinitely. What I want to happen is for DHCP_run()
to return DHCP_IP_LEASED
, which would indicate that the DHCP server has given the unit an address with which it can send and receive packets.
Anyone have any idea what’s wrong, or what to try in order to debug this?