Wiznet Wiz820io (W5200) Module – No data on MISO Line

avrspi

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

enter image description here

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.