Can't update Sn_RX_RD on WizNet550io

#1

I’m having trouble updating the Sn_RX_RD register after a UDP packet has arrived. I’ve written a small monitor program that let’s me work with the registers so its easier to test.
The test is as follows: After the module is initialized I send a block of UDP messages from the Vixen Show software which embeds DMX512A light show information into Ethernet UDP packets. I then stop Vixen and look at the status of the WizNet550io. Below is the terminal session and comments describing the problem which is that I cannot update receive register. Even after writing a RECV command to the Command register. The data below shows that the WizNet has received at least 3 packets since the E1.31 Sequence number is correctly incremented.

So the data is being received by the WizNet550io and matches what I’ve seen with WireShark. The 8 byte UDP headers match the information. But I can’t change the value of the read pointer.
Suggestions?

Receiving ANSI E1.31 DMX512 packets sent by Vixen 3.0 and verified by WireShark.

WizNet550io parameters.
Gateway Address 192.168.0.1
Subnet Mask FF, FF, FF, 00
Source MAC Address 00, 08, DC, 1D, 4C, 4F
Source IP Address 192.168.0.125

Mode: 82, Cmd: 00
Interrupt: 04, Status: 22
Src Port: 15C0
Dest.Adr 01 00 5E 00 7F 00, Dest.IP 239.255.0.1, Dest Port: 15C0
Max Seg. Size 05C0
Sn_RX_RSR 079A, Sn_RX_RD 008B, Sn_RX_WR 0825

First 4 bytes describe source IP, the next 2 the Port # and the last 2 the
length of the UDP data which is the E1.31 DMX packet.

Sending IP #192.168.0.104, Sending Port # 50150
Length of ANSI E1.31 Packet is 0x83. Packet #0x65 at 0x102
008B: C0 A8 00 68 C3 E6 00 83 00 10 00 00 41 53 43 2D
009B: 45 31 2E 31 37 00 00 00 70 73 00 00 00 04 E4 43
00AB: 33 E9 36 F8 48 43 B6 98 02 59 F4 36 6D 5E 70 5D
00BB: 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00
00CB: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00DB: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00EB: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00FB: 00 00 00 00 64 00 00 65 00 00 01 70 10 02 A1 00
010B: 00 00 01 00 06 00 00 00 00 00 00
Length of ANSI E1.31 Packet is 0x83. Packet #0x66 at 0x18D
0116: C0 A8 00 68 C3 E6 00 83 00 10 00 00 41 53 43 2D
0126: 45 31 2E 31 37 00 00 00 70 73 00 00 00 04 E4 43
0136: 33 E9 36 F8 48 43 B6 98 02 59 F4 36 6D 5E 70 5D
0146: 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00
0156: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0166: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0176: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0186: 00 00 00 00 64 00 00 66 00 00 01 70 10 02 A1 00
0196: 00 00 01 00 06 00 00 00 00 00 00
Length of ANSI E1.31 Packet is 0x83. Packet #0x67 at 0x218
01A1: C0 A8 00 68 C3 E6 00 83 00 10 00 00 41 53 43 2D
01B1: 45 31 2E 31 37 00 00 00 70 73 00 00 00 04 E4 43
01C1: 33 E9 36 F8 48 43 B6 98 02 59 F4 36 6D 5E 70 5D
01D1: 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00
01E1: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01F1: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0201: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0211: 00 00 00 00 64 00 00 67 00 00 01 70 10 02 A1 00
0221: 00 00 01 00 06 00 00 00 00 00 00

Following the instructions at:
wizwiki.net/wiki/doku.php?id=pro … p_function

Reg:0x28 <-- 0x0116
Reg:0x01 <-- 0x40

Mode: 82, Cmd: 00
Interrupt: 04, Status: 22
Src Port: 15C0
Dest.Adr 01 00 5E 00 7F 00, Dest.IP 239.255.0.1, Dest Port: 15C0
Max Seg. Size 05C0
Sn_RX_RSR 079A, Sn_RX_RD 008B, Sn_RX_WR 0825

Even writing Sn_RX_RSR+Sn_RX_RD to Sn_RX_RD and sending a RECV to the control register doesn’t change the read pointer.
Reg:0x28 <-- 0x0825
Reg:0x01 <-- 0x40
Mode: 82, Cmd: 00
Interrupt: 04, Status: 22
Src Port: 15C0
Dest.Adr 01 00 5E 00 7F 00, Dest.IP 239.255.0.1, Dest Port: 15C0
Max Seg. Size 05C0
Sn_RX_RSR 079A, Sn_RX_RD 008B, Sn_RX_WR 0825

#2

Hi,

Did you wait to hold command register until it is cleared??

#3

Yes. The CMD register is 00 before I write 0x40 to it. I know my code writes to the device correctly because otherwise I’d not be able to set up IP address or the gateway or port #. So something else is preventing the RECV command from updating the Read Pointer. The question is what?
Thanks
John

Mode: 82, Cmd: 00
Interrupt: 04, Status: 22
Src Port: 15C0
Dest.Adr 01 00 5E 00 7F 00, Dest.IP 239.255.0.1, Dest Port: 15C0
Max Seg. Size 05C0
Sn_RX_RSR 079A, Sn_RX_RD 008B, Sn_RX_WR 0825

Reg:0x28 <-- 0x0116
Reg:0x01 <-- 0x40

Mode: 82, Cmd: 00
Interrupt: 04, Status: 22
Src Port: 15C0
Dest.Adr 01 00 5E 00 7F 00, Dest.IP 239.255.0.1, Dest Port: 15C0
Max Seg. Size 05C0
Sn_RX_RSR 079A, Sn_RX_RD 008B, Sn_RX_WR 0825

#4

I added code to check that the CMD was 0 before I wrote. That changed how things operated a little but not enough.
I then found that the SPI library I used was designed to work with TTL shift registers and reads MISO back when it writes out MOSI and what it reads goes on top of what it wrote.
Using a temporary buffer would have fixed that but slowed down the code with an extra copy. I modified the write buffer routine to not step on the data and then things worked properly. Very subtle and hard to find problem.
I now have the Vixen Light show software sending UDP packets to my Freescale M9S12 through the WizNet and from the M9S12 out the CAN bus to the LED lamps.

#5

I like it when people post solutions to the issues they have been complaining about. Here’s the more detailed explanation.
This function SPI1_writebytes() is wrong when used as follows:

BYTE WizNetBuffer[256];

void
WizNetPut(BYTE blk, WORD adr, int cnt, PBYTE pbuf) {
    SPI1_CS(0);
    SPI1_write((BYTE)(adr>>8));
    SPI1_write((BYTE)adr);
    SPI1_write((blk << 3) | 0x04);
    SPI1_writebytes(pbuf, cnt);
    SPI1_CS(1);
}

void 
SPI1_writebytes(PBYTE buf, int cnt) {
  WORD spi_i;
  BYTE b;
    for (spi_i=0; spi_i<cnt; spi_i++) {
        while(!SPI1SR_SPTEF);
        SPI1DR = *buf;
        while (!SPI1SR_SPIF);
        *buf++ = SPI1DR;
    }
}

Using a general purpose buffer, 18 bytes of data have been put into the WizNetBuffer and now sent out. Because of the way the incorrect SPI1_writebytes works the results in WizNetBuffer have been written over by whatever was in the SPI receive register after sending each byte. Not a problem in this case.

WizNetPut(0, 1, 18, (PBYTE)&WizNetBuffer[0]);      

But if the pointer to WizNetPut was to a data structure like a structure that held the UDP header then the data inside the header would be set to zero. So updating the Sn_RX_RD Pointer register with a new value destroyed it for the next usage. The solution was to ignore data on the SPI receive side.

void 
SPI1_writebytes(PBYTE buf, int cnt) {
  WORD spi_i;
  BYTE b;
    for (spi_i=0; spi_i<cnt; spi_i++) {
        while(!SPI1SR_SPTEF);
        SPI1DR = *buf++;            // Increment pointer here.
        while (!SPI1SR_SPIF);
        b = SPI1DR;                    // Read data here and discard.
    }
}