I had a working circuit with Wiznet W5100, but to get better performance I switched over to Wiznet W5200 (in Wiz820io module). This involved rewiring the pins, changing the register address and also the Read/Write code for the ethernet module as this chip supports Burst Write.
Datasheet here
However (this has me totally stumped), when I power on the circuit and read the registers that I have just written to (GATEWAY, IP etc), all I get is 0x00.
This is what I got using logic analyzer
The MISO line is just flat. No data being sent back to the master.
These are my read/write routines for the Ethernet module :
//OP CODES (TO BE OR'ED WITH UPPER 7 BITS OF ADDRESS)
#define W5200_WRITE 0x80
#define W5200_READ 0x00
//BURST WRITING FOR W5200. FOR DATA LENGTH = 1, DEFAULTS TO BYTE WRITE
void ETHERNET_WRITE(uint16_t address, uint8_t *data, uint16_t len)
{
W5200_SS_LOW; //SET W5200 SS LOW
SPI_TXRX((address & 0xFF00)>>8); //WRITE HIGH BYTE OF 2 BYTE ADDRESS
while(SPI_DATA_RECEIVED==0);
SPI_TXRX((address & 0x00FF)); //WRITE LOW BYTE OF 2 BYTE ADDRESS
while(SPI_DATA_RECEIVED==0);
SPI_TXRX(W5200_WRITE | ((len & 0x7F00)>>8)); //WRITE OPCODE | DATA LENGTH (UPPER 7 BITS)
while(SPI_DATA_RECEIVED==0);
SPI_TXRX(len & 0x00FF); //DATA LENGTH (LOWER 8 BITS)
while(SPI_DATA_RECEIVED==0);
for(uint16_t i=0; i<len; i++)
{
SPI_TXRX(data[i]); //WRITE DATA
while(SPI_DATA_RECEIVED==0);
}
W5200_SS_HIGH; //TURN BACK SS HIGH
}
//BURST READING FOR W5200. FOR DATA LENGTH = 1, DEFAULTS TO BYTE READ
void ETHERNET_READ(uint16_t address, uint8_t len, uint8_t* retval)
{
W5200_SS_LOW; //SET W5200 SS LOW
SPI_TXRX((address & 0xFF00)>>8); //WRITE HIGH BYTE OF 2 BYTE ADDRESS
while(SPI_DATA_RECEIVED==0);
SPI_TXRX(address & 0x00FF); //WRITE LOW BYTE OF 2 BYTE ADDRESS
while(SPI_DATA_RECEIVED==0);
SPI_TXRX(W5200_READ | ((len & 0x7F00)>>8)); //READ OPCODE | DATA LENGTH (UPPER 7 BITS)
while(SPI_DATA_RECEIVED==0);
SPI_TXRX(len & 0x00FF); //DATA LENGTH (LOWER 8 BITS)
while(SPI_DATA_RECEIVED==0);
for(uint8_t i=0; i<len; i++)
{
SPI_TXRX(0x00); //WRITE DUMMY DATA TO READ DATA
while(SPI_DATA_RECEIVED==0);
retval[i] = SPI_RX_DATA;
}
W5200_SS_HIGH; //SET SS HIGH
}
Initially I was powering this module using LM2950 33, but since it's max current output is 100mA, I moved over to LM317 adjustable LDO that is now powering the module with 3.14V
This is my ethernet intialization code
void ETHERNET_INIT(uint16_t ip_address, uint16_t subnet_address, uint16_t gateway_address, uint16_t mac)
{
uint8_t val[6];
uint8_t retval[6];
uint8_t i;
W5200_RESET_LOW;
_delay_us(50);
W5200_RESET_HIGH;
for(i=0;i<20; i++)
{
_delay_ms(20);
}
val[0] = MR_RST;
ETHERNET_WRITE(MR, val,1);
ETHERNET_READ(MR, 1, retval);
while(retval[0] !=0) {ETHERNET_READ(MR, 1, retval);}
printf("*** Ethernet ****\r");
//if(ETHERNET_DEBUG)
//{
ETHERNET_READ(MR, 1, retval);
printf("Reading MR : %u\r", retval[0]);
//}
//set IP Address
EEPROM_READ(ip_address, 4, retval);
ETHERNET_WRITE(SIPR, retval, 4);
//if(ETHERNET_DEBUG)
//{
ETHERNET_READ(SIPR, 4, retval);
printf("IP Address : %u.%u.%u.%u\r",retval[0],retval[1],retval[2],retval[3]);
//}
//set subnet mask
EEPROM_READ(subnet_address, 4, retval);
ETHERNET_WRITE(SUBR, retval, 4);
//if(ETHERNET_DEBUG)
//{
ETHERNET_READ(SUBR, 4, retval);
printf("Subnet Mask : %u.%u.%u.%u\r",retval[0],retval[1],retval[2],retval[3]);
//}
//set gateway address
EEPROM_READ(gateway_address, 4, retval);
ETHERNET_WRITE(GWR, retval, 4);
//if(ETHERNET_DEBUG)
//{
ETHERNET_READ(GWR, 4, retval);
printf("Gateway ip Address : %u.%u.%u.%u\r",retval[0],retval[1],retval[2],retval[3]);
//}
//set mac address
EEPROM_READ(mac, 6, retval);
ETHERNET_WRITE(SHAR, retval, 6);
//if(ETHERNET_DEBUG)
//{
ETHERNET_READ(SHAR, 6, retval);
printf("mac Address : %02X.%02X.%02X.%02X.%02X.%02X\r",retval[0],retval[1],retval[2],retval[3],retval[4],retval[5]);
//}
//set interrupt high time
val[0] = 1;
ETHERNET_WRITE(INTLEVEL, val, 1);
//set TX and RX memory to 2KB per socket
//val[0] = 0x55;
//ETHERNET_WRITE(RMSR, val, 1);
//ETHERNET_WRITE(TMSR, val, 1);
//set TX = 8Kb RX = 8Kb for Sock 0 & Sock 1
val[0] = 0x08;
ETHERNET_WRITE(SOCKET_0_REGISTER_BASE + SN_RX_MEMSIZE, val, 1);
ETHERNET_WRITE(SOCKET_0_REGISTER_BASE + SN_TX_MEMSIZE, val, 1);
ETHERNET_WRITE(SOCKET_1_REGISTER_BASE + SN_RX_MEMSIZE, val, 1);
ETHERNET_WRITE(SOCKET_1_REGISTER_BASE + SN_TX_MEMSIZE, val, 1);
val[0] = 0x00;
ETHERNET_WRITE(SOCKET_2_REGISTER_BASE + SN_RX_MEMSIZE, val, 1);
ETHERNET_WRITE(SOCKET_2_REGISTER_BASE + SN_TX_MEMSIZE, val, 1);
ETHERNET_WRITE(SOCKET_3_REGISTER_BASE + SN_RX_MEMSIZE, val, 1);
ETHERNET_WRITE(SOCKET_3_REGISTER_BASE + SN_TX_MEMSIZE, val, 1);
ETHERNET_WRITE(SOCKET_4_REGISTER_BASE + SN_RX_MEMSIZE, val, 1);
ETHERNET_WRITE(SOCKET_4_REGISTER_BASE + SN_TX_MEMSIZE, val, 1);
ETHERNET_WRITE(SOCKET_5_REGISTER_BASE + SN_RX_MEMSIZE, val, 1);
ETHERNET_WRITE(SOCKET_5_REGISTER_BASE + SN_TX_MEMSIZE, val, 1);
ETHERNET_WRITE(SOCKET_6_REGISTER_BASE + SN_RX_MEMSIZE, val, 1);
ETHERNET_WRITE(SOCKET_6_REGISTER_BASE + SN_TX_MEMSIZE, val, 1);
ETHERNET_WRITE(SOCKET_7_REGISTER_BASE + SN_RX_MEMSIZE, val, 1);
ETHERNET_WRITE(SOCKET_7_REGISTER_BASE + SN_TX_MEMSIZE, val, 1);
//set RTR - retry time value register for timeout @ 2000us
val[0] = 0x07;
val[1] = 0xD0;
ETHERNET_WRITE(RTR, val, 2);
//if(ETHERNET_DEBUG)
//{
ETHERNET_READ(RTR, 2, retval);
printf("rtr : %x:%x\r", retval[0], retval[1]);
//}
//set RCR - max retry count to 8
val[0] = 0x08;
ETHERNET_WRITE(RCR, val, 1);
//if(ETHERNET_DEBUG)
//{
ETHERNET_READ(RCR, 1, retval);
printf("rcr : %u\r", retval[0]);
//}
//enable mask for socket 1 interrupt
val[0] = IMR_S1_INT;
ETHERNET_WRITE(IMR, val, 1);
if(ETHERNET_DEBUG)
{
ETHERNET_READ(IMR, 1, retval);
printf("IMR : 0x%x\r",retval[0]);
}
}
Any ideas?
Best Answer
It's working now. It was the Reset line going from my AVR to the W5200 module. It was never going down to 0V, hence the unit was never getting resetted.
Not sure how I managed to screw up the i/o pin. Connecting the reset line to a different pin on the AVR solved the issue.