CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

W5200 (wiz820io) code

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
thefloyd



Joined: 02 Sep 2009
Posts: 46

View user's profile Send private message

W5200 (wiz820io) code
PostPosted: Fri Dec 23, 2016 5:20 pm     Reply with quote

I meant to post this code some time ago, but I always wanted to clean it all up and merge it with some W5100 code I'd been working on and work out a set of #DEFINEs so that the end user could switch between the two. I never did, but the code works and I figure it may help someone out.

Honestly, I haven't touched most of this in a couple of years but it works serving up some web pages off of a PIC for some home control stuff I was working on. I've since moved over to BLE with the RN4020 which is way better suited to my needs (I'm awful at coding GUIs, best to just leverage the work CCS has already done here for a usable smartphone app). Some example servers / services are at the bottom. There's some debugging statements and other stuff that was specific to my hardware (I think I've commented them all, but apologies if I've missed any), so this isn't a copy-paste & expect it to work exercise, but this is a pretty good starting point for someone with the w5200/wiz820io.

Looking back I've done some things in a way that I'm not really sure why I originally did them that way (like a global variable for mac address?). I know there was a reason, might have been trying to debug or work around something. There's cleaner ways of doing some of that stuff here, so feel free to clean it up.

There's an example here for a UDP echo server. I've got some other code for dhcp client and http server that, quite frankly, I can barely decipher after 2+ years. If I can find the time to clean them up / rewrite them in a usable way I'll append them later (basically, this code works and I'm least embarrassed to share it Very Happy).

first up, w5200.h:
Code:

// W5200 Commands (from W5200 data sheet).
#define W5200_WRITE_CMD  0x80
#define W5200_READ_CMD   0x00

// W5200 Register addresses (from W5200 data sheet).
#define W5200_MR_REG   0x0000
#define W5200_GAR0_REG 0x0001
#define W5200_GAR1_REG 0x0002
#define W5200_GAR2_REG 0x0003
#define W5200_GAR3_REG 0x0004

#define W5200_SUBR0_REG 0x0005
#define W5200_SUBR1_REG 0x0006
#define W5200_SUBR2_REG 0x0007
#define W5200_SUBR3_REG 0x0008

#define W5200_SHAR0_REG 0x0009
#define W5200_SHAR1_REG 0x000A
#define W5200_SHAR2_REG 0x000B
#define W5200_SHAR3_REG 0x000C
#define W5200_SHAR4_REG 0x000D
#define W5200_SHAR5_REG 0x000E

#define W5200_SIPR0 0x000F
#define W5200_SIPR1 0x0010
#define W5200_SIPR2 0x0011
#define W5200_SIPR3 0x0012

#define W5200_IR 0x0015
#define W5200_IMR 0x0016

#define W5200_RTR0 0x0017
#define W5200_RTR1 0x0018

#define W5200_RCR 0x0019

// Receive memory size reigster
#define RMSR     0x001A

// Transmit memory size reigster
#define TMSR      0x001B
// Authentication type register address in PPPoE mode
#define PATR0      0x001C
#define PATR1      0x001D
#define PPPALGO    0x001E
#define W5200_VERSION 0x001F
#define PTIMER  0x0028
#define PMAGIC  0x0029
// Unreachable IP register address in UDP mode
#define UIPR0    0x002A
// Unreachable Port register address in UDP mode
#define UPORT0      0x002E
// Interrupt low level timer
#define W5200_INTLEVEL0 0x0030
#define W5200_INTLEVEL1 0x0031
// Socket Interrupt
#define W5200_IR2 0x0034
// PHY Status
#define W5200_PSTATUS 0x0035
// Interrupt Mask
#define W5200_IMR2 0x0036

// sockets
#define SOCK_BASE       0x4000
#define SOCK_MR         (SOCK_BASE + 0x00)
#define SOCK_CR         (SOCK_BASE + 0x01)
#define SOCK_IR         (SOCK_BASE + 0x02)
#define SOCK_SR         (SOCK_BASE + 0x03)
#define SOCK_PORT0      (SOCK_BASE + 0x04)
#define SOCK_PORT1      (SOCK_BASE + 0x05)
#define SOCK_DHAR0      (SOCK_BASE + 0x06)
#define SOCK_DHAR1      (SOCK_BASE + 0x07)
#define SOCK_DHAR2      (SOCK_BASE + 0x08)
#define SOCK_DHAR3      (SOCK_BASE + 0x09)
#define SOCK_DHAR4      (SOCK_BASE + 0x0A)
#define SOCK_DHAR5      (SOCK_BASE + 0x0B)
#define SOCK_DIPR0      (SOCK_BASE + 0x0C)
#define SOCK_DIPR1      (SOCK_BASE + 0x0D)
#define SOCK_DIPR2      (SOCK_BASE + 0x0E)
#define SOCK_DIPR3      (SOCK_BASE + 0x0F)
#define SOCK_DPORT0     (SOCK_BASE + 0x10)
#define SOCK_DPORT1     (SOCK_BASE + 0x11)
#define SOCK_MSSR0      (SOCK_BASE + 0x12)
#define SOCK_MSSR1      (SOCK_BASE + 0x13)
#define SOCK_PROTO      (SOCK_BASE + 0x14)
#define SOCK_TOS        (SOCK_BASE + 0x15)
#define SOCK_TTL        (SOCK_BASE + 0x16)
#define SOCK_RXMEM_SIZE (SOCK_BASE + 0x1E)
#define SOCK_TXMEM_SIZE (SOCK_BASE + 0x1F)
#define SOCK_TX_FSR0    (SOCK_BASE + 0x20)
#define SOCK_TX_FSR1    (SOCK_BASE + 0x21)
#define SOCK_TX_RD0     (SOCK_BASE + 0x22)
#define SOCK_TX_RD1     (SOCK_BASE + 0x23)
#define SOCK_TX_WR0     (SOCK_BASE + 0x24)
#define SOCK_TX_WR1     (SOCK_BASE + 0x25)
#define SOCK_RX_RSR0    (SOCK_BASE + 0x26)
#define SOCK_RX_RSR1    (SOCK_BASE + 0x27)
#define SOCK_RX_RD0     (SOCK_BASE + 0x28)
#define SOCK_RX_RD1     (SOCK_BASE + 0x29)
#define SOCK_RX_WR0     (SOCK_BASE + 0x2A)
#define SOCK_RX_WR1     (SOCK_BASE + 0x2B)
#define SOCK_IMR        (SOCK_BASE + 0x2C)
#define SOCK_FRAG0      (SOCK_BASE + 0x2D)
#define SOCK_FRAG1      (SOCK_BASE + 0x2E)

//*
//* Socket 0 registers
//*
#define S0_BASE 0x4000
#define S0_MR 0x4000
#define S0_CR 0x4001
#define S0_IR 0x4002
#define S0_SR 0x4003
#define S0_PORT0 0x4004
#define S0_PORT1 0x4005
#define S0_DHAR0 0x4006
#define S0_DHAR1 0x4007
#define S0_DHAR2 0x4008
#define S0_DHAR3 0x4009
#define S0_DHAR4 0x400A
#define S0_DHAR5 0x400B
#define S0_DIPR0 0x400C
#define S0_DIPR1 0x400D
#define S0_DIPR2 0x400E
#define S0_DIPR3 0x400F
#define S0_DPORT0 0x4010
#define S0_DPORT1 0x4011
#define S0_MSSR0 0x4012
#define S0_MSSR1 0x4013
#define S0_PROTO 0x4014
#define S0_TOS 0x4015
#define S0_TTL 0x4016
#define S0_RXMEM_SIZE 0x401E
#define S0_TXMEM_SIZE 0x401F
#define S0_TX_FSR0 0x4020
#define S0_TX_FSR1 0x4021
#define S0_TX_RD0 0x4022
#define S0_TX_RD1 0x4023
#define S0_TX_WR0 0x4024
#define S0_TX_WR1 0x4025
#define S0_RX_RSR0 0x4026
#define S0_RX_RSR1 0x4027
#define S0_RX_RD0 0x4028
#define S0_RX_RD1 0x4029
#define S0_RX_WR0 0x402A
#define S0_RX_WR1 0x402B
#define S0_IMR 0x402C
#define S0_FRAG0 0x402D
#define S0_FRAG1 0x402E
//*
//* Socket 1 registers
//*
#define S1_BASE 0x4100
#define S1_MR 0x4100
#define S1_CR 0x4101
#define S1_IR 0x4102
#define S1_SR 0x4103
#define S1_PORT0 0x4104
#define S1_PORT1 0x4105
#define S1_DHAR0 0x4106
#define S1_DHAR1 0x4107
#define S1_DHAR2 0x4108
#define S1_DHAR3 0x4109
#define S1_DHAR4 0x410A
#define S1_DHAR5 0x410B
#define S1_DIPR0 0x410C
#define S1_DIPR1 0x410D
#define S1_DIPR2 0x410E
#define S1_DIPR3 0x410F
#define S1_DPORT0 0x4110
#define S1_DPORT1 0x4111
#define S1_MSSR0 0x4112
#define S1_MSSR1 0x4113
#define S1_PROTO 0x4114
#define S1_TOS 0x4115
#define S1_TTL 0x4116
#define S1_RXMEM_SIZE 0x411E
#define S1_TXMEM_SIZE 0x411F
#define S1_TX_FSR0 0x4120
#define S1_TX_FSR1 0x4121
#define S1_TX_RD0 0x4122
#define S1_TX_RD1 0x4123
#define S1_TX_WR0 0x4124
#define S1_TX_WR1 0x4125
#define S1_RX_RSR0 0x4126
#define S1_RX_RSR1 0x4127
#define S1_RX_RD0 0x4128
#define S1_RX_RD1 0x4129
#define S1_RX_WR0 0x412A
#define S1_RX_WR1 0x412B
#define S1_IMR 0x412C
#define S1_FRAG0 0x412D
#define S1_FRAG1 0x412E

//*
//* Socket 7 registers
//*

#define S7_BASE 0x4700
#define S7_MR 0x4700
#define S7_CR 0x4701
#define S7_IR 0x4702
#define S7_SR 0x4703
#define S7_PORT0 0x4704
#define S7_PORT1 0x4705
#define S7_DHAR0 0x4706
#define S7_DHAR1 0x4707
#define S7_DHAR2 0x4708
#define S7_DHAR3 0x4709
#define S7_DHAR4 0x470A
#define S7_DHAR5 0x470B
#define S7_DIPR0 0x470C
#define S7_DIPR1 0x470D
#define S7_DIPR2 0x470E
#define S7_DIPR3 0x470F
#define S7_DPORT0 0x4710
#define S7_DPORT1 0x4711
#define S7_MSSR0 0x4712
#define S7_MSSR1 0x4713
#define S7_PROTO 0x4714
#define S7_TOS 0x4715
#define S7_TTL 0x4716
#define S7_RXMEM_SIZE 0x471E
#define S7_TXMEM_SIZE 0x471F
#define S7_TX_FSR0 0x4720
#define S7_TX_FSR1 0x4721
#define S7_TX_RD0 0x4722
#define S7_TX_RD1 0x4723
#define S7_TX_WR0 0x4724
#define S7_TX_WR1 0x4725
#define S7_RX_RSR0 0x4726
#define S7_RX_RSR1 0x4727
#define S7_RX_RD0 0x4728
#define S7_RX_RD1 0x4729
#define S7_RX_WR0 0x472A
#define S7_RX_WR1 0x472B
#define S7_IMR 0x472C
#define S7_FRAG0 0x472D
#define S7_FRAG1 0x472E


//  MODE register values
#define MR_RST        0x80 // reset
#define MR_PB         0x10 // ping block
#define MR_PPPOE      0x08 // enable pppoe
#define MR_LB         0x04 // little or big endian selector in indirect mode
#define MR_AI         0x02 // auto-increment in indirect mode
#define MR_IND        0x01 // enable indirect mode

//  IR register values
#define IR_CONFLICT   0x80 // check ip confict
#define IR_UNREACH    0x40 // get the destination unreachable message in UDP sending
#define IR_PPPoE      0x20 // get the PPPoE close message
#define IR_SOCK(ch)   (0x01 << ch) // check socket interrupt

//  Sn_MR values
#define S_MR_CLOSE    0x00      // unused socket
#define S_MR_TCP      0x01      // TCP
#define S_MR_UDP      0x02      // UDP ******************
#define S_MR_IPRAW    0x03      // IP LAYER RAW SOCK
#define S_MR_MACRAW   0x04      // MAC LAYER RAW SOCK
#define S_MR_PPPOE    0x05      // PPPoE
#define S_MR_ND       0x20      // No Delayed Ack(TCP) flag
#define S_MR_MULTI    0x80      // support multicating

//  Sn_CR values
#define S_CR_OPEN     0x01      // initialize or open socket  ****************************
#define S_CR_LISTEN   0x02      // wait connection request in tcp mode(Server mode)
#define S_CR_CONNECT  0x04      // send connection request in tcp mode(Client mode)
#define S_CR_DISCON   0x08      // send closing reqeuset in tcp mode
#define S_CR_CLOSE    0x10      // close socket
#define S_CR_SEND     0x20      // updata txbuf pointer, send data
#define S_CR_SEND_MAC   0x21      // send data with MAC address, so without ARP process
#define S_CR_SEND_KEEP  0x22      //  send keep alive message
#define S_CR_RECV     0x40      // update rxbuf pointer, recv data

//  Sn_IR values
#define S_IR_SEND_OK         0x10      // complete sending
#define S_IR_TIMEOUT         0x08      // assert timeout
#define S_IR_RECV            0x04      // receiving data
#define S_IR_DISCON          0x02      // closed socket
#define S_IR_CON             0x01      // established connection

//  Sn_SR values
#define SOCK_CLOSED           0x00      // closed
#define SOCK_INIT             0x13      // init state
#define SOCK_LISTEN           0x14      // listen state
#define SOCK_SYNSENT          0x15      // connection state
#define SOCK_SYNRECV          0x16      // connection state
#define SOCK_ESTABLISHED      0x17      // success to connect
#define SOCK_FIN_WAIT         0x18      // closing state
#define SOCK_CLOSING          0x1A      // closing state
#define SOCK_TIME_WAIT        0x1B      // closing state
#define SOCK_CLOSE_WAIT       0x1C      // closing state
#define SOCK_LAST_ACK         0x1D      // closing state
#define SOCK_UDP              0x22      // udp socket **********************
#define SOCK_IPRAW            0x32      // ip raw mode socket
#define SOCK_MACRAW           0x42      // mac raw mode socket
#define SOCK_PPPOE            0x5F      // pppoe socket

//  IP PROTOCOL
#define IPPROTO_IP              0           // Dummy for IP
#define IPPROTO_ICMP            1           // Control message protocol
#define IPPROTO_IGMP            2           // Internet group management protocol
#define IPPROTO_GGP             3           // Gateway^2 (deprecated)
#define IPPROTO_TCP             6           // TCP
#define IPPROTO_PUP             12          // PUP
#define IPPROTO_UDP             17          // UDP
#define IPPROTO_IDP             22          // XNS idp
#define IPPROTO_ND              77          // UNOFFICIAL net disk protocol
#define IPPROTO_RAW             255         // Raw IP packet

#define chip_base_address               0x0000
#define RX_memory_base_address          0xC000
#define RX_MASK                         0x0800 - 1
#define gS0_RX_BASE                     chip_base_address + RX_memory_base_address
#define gS0_RX_MASK                     0x0800 - 1
#define gS1_RX_BASE                     gS0_RX_BASE + (gS0_RX_MASK + 1)
#define gS1_RX_MASK                     0x0800 - 1
#define gS2_RX_BASE                     gS1_RX_BASE + (gS1_RX_MASK + 1)
#define gS2_RX_MASK                     0x0800 - 1
#define gS3_RX_BASE                     gS2_RX_BASE + (gS2_RX_MASK + 1)
#define gS3_RX_MASK                     0x0800 - 1
#define gS4_RX_BASE                     gS3_RX_BASE + (gS3_RX_MASK + 1)
#define gS4_RX_MASK                     0x0800 - 1
#define gS5_RX_BASE                     gS4_RX_BASE + (gS4_RX_MASK + 1)
#define gS5_RX_MASK                     0x0800 - 1
#define gS6_RX_BASE                     gS5_RX_BASE + (gS5_RX_MASK + 1)
#define gS6_RX_MASK                     0x0800 - 1
#define gS7_RX_BASE                     gS6_RX_BASE + (gS6_RX_MASK + 1);
#define gS7_RX_MASK                     0x0800 - 1
#define TX_memory_base_address          0x8000
#define TX_MASK                         0x0800 - 1
#define gS0_TX_BASE                     chip_base_address + TX_memory_base_address
#define gS0_TX_MASK                     0x0800 - 1
#define gS1_TX_BASE                     gS0_TX_BASE + (gS0_TX_MASK + 1)
#define gS1_TX_MASK                     0x0800 - 1
#define gS2_TX_BASE                     gS1_TX_BASE + (gS1_TX_MASK + 1)
#define gS2_TX_MASK                     0x0800 - 1
#define gS3_TX_BASE                     gS2_TX_BASE + (gS2_TX_MASK + 1)
#define gS3_TX_MASK                     0x0800 - 1
#define gS4_TX_BASE                     gS3_TX_BASE + (gS3_TX_MASK + 1)
#define gS4_TX_MASK                     0x0800 - 1
#define gS5_TX_BASE                     gS4_TX_BASE + (gS4_TX_MASK + 1)
#define gS5_TX_MASK                     0x0800 - 1
#define gS6_TX_BASE                     gS5_TX_BASE + (gS5_TX_MASK + 1)
#define gS6_TX_MASK                     0x0800 - 1
#define gS7_TX_BASE                     gS6_TX_BASE + (gS6_TX_MASK + 1)
#define gS7_TX_MASK                     0x0800 - 1


Next up, some routines I wrote to talk to the module:

w5200.c
Code:

#include <w5200.h>

void w5200_write_reg(unsigned int16 addr, unsigned int8 data)
{
  unsigned int16 data_len = (unsigned int16) 1;
  output_low(W5200_CS);
  spi_write(addr >> 8);  // Send address msb
  spi_write(addr);       // Send address lsb
  spi_write(W5200_WRITE_CMD | ((data_len & 0x7F00) >> 8));
  spi_write(data_len & 0x00FF);
  spi_write(data);
  output_high(W5200_CS);
}

unsigned int8 w5200_read_reg(unsigned int16 addr)
{
  unsigned int8 retval;
  unsigned int16 data_len = (unsigned int16) 1;
  output_low(W5200_CS);
  spi_write(addr >> 8);  // Send address msb
  spi_write(addr);       // Send address lsb
  spi_write(W5200_READ_CMD | ((data_len & 0x7F00) >> 8));
  spi_write(data_len & 0x00FF);
  retval = spi_read(0);  // Read data from W5200
  output_high(W5200_CS);
  return(retval);
}

void w5200_burst_write(unsigned int16 addr, char *data, unsigned int16 len) {
  unsigned int16 i16;

  output_low(W5200_CS);
  spi_write(addr >> 8);
  spi_write(addr);
  spi_write(W5200_WRITE_CMD | ((len & 0x7F00) >> 8));
  spi_write(len & 0x00FF);
  for(i16=0;i16<len;++i16) {
    spi_write(data[i16]);
  }
  output_high(W5200_CS);
}

void w5200_burst_read(unsigned int16 addr, char *data, unsigned int16 len) {
  unsigned int16 i16;

  output_low(W5200_CS);
  spi_write(addr >> 8);  // Send address msb
  spi_write(addr);       // Send address lsb
  spi_write(W5200_READ_CMD | ((len & 0x7F00) >> 8));
  spi_write(len & 0x00FF);
  for(i16=0;i16<len;++i16) {
    data[i16] = spi_read(0);
  }
  data[i16] = "\0";
  output_high(W5200_CS);
}

void w5200_init(void)
{
  output_low(W5200_RS);
  delay_us(10);
  output_high(W5200_RS);
  delay_ms(200);
  output_high(W5200_CS);
  w5200_write_reg(W5200_MR_REG, 0b10000000);
  w5200_write_reg(RMSR, 0x55);    //memory for TX and RX
  w5200_write_reg(TMSR, 0x55); 
  w5200_write_reg(W5200_IMR,0xFF);
  w5200_write_reg(W5200_RTR0,0x07); //200Ms 0x07D0
  w5200_write_reg(W5200_RTR1,0xD0);
}

void w5200_set_mac() {
  unsigned int8 i;
 
  for(i=0;i<6;++i) {
    w5200_write_reg((W5200_SHAR0_REG + i), mac_addr[i]);
  }
}

void w5200_set_ip(unsigned int8 byte0, byte1, byte2, byte3) {
  w5200_write_reg(W5200_SIPR0, byte0);
  w5200_write_reg(W5200_SIPR1, byte1);
  w5200_write_reg(W5200_SIPR2, byte2);
  w5200_write_reg(W5200_SIPR3, byte3);
}

void w5200_set_gw(unsigned int8 byte0, byte1, byte2, byte3) {
  w5200_write_reg(W5200_GAR0_REG, byte0);
  w5200_write_reg(W5200_GAR1_REG, byte1);
  w5200_write_reg(W5200_GAR2_REG, byte2);
  w5200_write_reg(W5200_GAR3_REG, byte3);
}

void w5200_set_subnet(unsigned int8 byte0, byte1, byte2, byte3) {
  w5200_write_reg(W5200_SUBR0_REG, byte0);
  w5200_write_reg(W5200_SUBR1_REG, byte1);
  w5200_write_reg(W5200_SUBR2_REG, byte2);
  w5200_write_reg(W5200_SUBR3_REG, byte3);
}

/*
void w5200_check_regs(void) {
  unsigned int8 ar[6], i;
  fprintf(DEBUG, "Read regs..\r\n");
 
  for(i=0;i<6;++i) {
    ar[i] = w5200_read_reg(W5200_SHAR0_REG + i);
  }
 
  fprintf(DEBUG, "My mac address: %x:%x:%x:%x:%x:%x\r\n", ar[0], ar[1], ar[2], ar[3], ar[4], ar[5]);
 
  for(i=0;i<4;++i) {
    ar[i] = w5200_read_reg(W5200_SIPR0 + i);
  }
 
  fprintf(DEBUG, "My address: %u.%u.%u.%u\r\n", ar[0], ar[1], ar[2], ar[3]);

  for(i=0;i<4;++i) {
    ar[i] = w5200_read_reg(W5200_GAR0_REG + i);
  }
  fprintf(DEBUG, "Gateway address: %u.%u.%u.%u\r\n", ar[0],ar[1],ar[2],ar[3]);
 
  for(i=0;i<4;++i) {
    ar[i] = w5200_read_reg(W5200_SUBR0_REG + i);
  }
 
  fprintf(DEBUG, "Subnet mask: %u.%u.%u.%u\r\n", ar[0],ar[1],ar[2],ar[3]);
}
*/

unsigned int16 w5200_write_data(unsigned int16 addr, char *buf, unsigned int16 len)
{
  unsigned int16 i;
  for(i=0;i<len;i++) {
    w5200_write_reg(addr,buf[i]);
    addr++;
  }
  return(addr);
}

// the below should go into a udp_stack.c or something like that file

void open_udp_socket(unsigned int16 socknum, unsigned int16 portnum) {
  socknum *= 0x0100;
  do {
    write_reg((SOCK_MR + socknum), S_MR_UDP);
    write_reg((SOCK_PORT0 + socknum), (portnum >> 8));
    write_reg((SOCK_PORT1 + socknum), (portnum));
    write_reg((SOCK_CR + socknum), S_CR_OPEN);
    if(read_reg(SOCK_SR + socknum) != SOCK_UDP) {
      write_reg((SOCK_CR + socknum), S_CR_CLOSE);
    }
  } while(read_reg(SOCK_SR + socknum) != SOCK_UDP);
}

void udp_echo_server(void) {
  unsigned int8 header_size, i8, status, s0_src_ip[4];
  unsigned int16 recv_size, offset, start_addr, udp_data_size, s0_src_port, ptr;
  unsigned int8 HeaderData[8];

  // receive

  do{
    recv_size = w5200_read_reg(S0_RX_RSR0);
    recv_size = ( recv_size << 8 ) + w5200_read_reg(S0_RX_RSR1);
  } while(recv_size == 0x0000);
  ptr = w5200_read_reg(S0_RX_RD0);
  ptr = ( ptr << 8 ) + w5200_read_reg(S0_RX_RD1);
  offset = ptr & gS0_RX_MASK;
  start_addr = gS0_RX_BASE + offset;
  header_size = 8;
  for(i8=0;i8<header_size;++i8)               // processing UDP header 8 bytes
  {
    HeaderData[i8] = w5200_read_reg(start_addr++);
  }
  for(i8=0; i8<4;++i8) {
    s0_src_ip[i8] = HeaderData[i8];
  }
  s0_src_port = make16(HeaderData[4], HeaderData[5]);
  udp_data_size = recv_size - header_size;
  if(udp_data_size >= BUFF_SIZE) {udp_data_size = (BUFF_SIZE - 1);}  // don't allow buffer overruns, instead truncate the string
  for(i8=0;i8<udp_data_size;++i8)
  {
    data[i8] = w5200_read_reg(start_addr++);
  }
  data[udp_data_size+1] = "\0"; // null terminate the string
  ptr += recv_size;
  w5200_write_reg(S0_RX_RD0, ptr >> 8);
  w5200_write_reg(S0_RX_RD1, ptr);
  w5200_write_reg(S0_CR,S_CR_RECV);
 
  // send

  start_addr = S0_DIPR0;
  for(i8=0;i8<4;++i8)
  {
    w5200_write_reg(start_addr++,s0_src_ip[i8]);
  }
  w5200_write_reg(S0_DPORT0, (s0_src_port >> 8));
  w5200_write_reg(S0_DPORT1, s0_src_port);
  ptr = w5200_read_reg(S0_TX_WR0);
  ptr = ( ptr << 8 ) + w5200_read_reg(S0_TX_WR1);
  offset = ptr & gS0_TX_MASK;
  start_addr = gS0_TX_BASE + offset;
  for(i8=0;i8<(udp_data_size);++i8)
  {
    w5200_write_reg(start_addr++,data[i8]);
  }
  ptr += udp_data_size;
  w5200_write_reg(S0_TX_WR0,(ptr >> 8));
  w5200_write_reg(S0_TX_WR1,(ptr));
  w5200_write_reg(S0_CR, S_CR_SEND);
  do {
    status = w5200_read_reg(S0_IR);
  } while (!bit_test(status, 4));
  w5200_write_reg(S0_CR,S_CR_DISCON);
  w5200_write_reg(S0_CR,S_CR_CLOSE);                 // done sending, close socket
}


finally - let's do something with all of that code:

main.c

Code:

#define FASTER_BUT_MORE_ROM // for string functions
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
#define W5200_CS PIN_C0
#define W5200_RS PIN_C1
#define W5200_INT PIN_B1
unsigned int8 mac_addr[6];

#define BUFF_SIZE 128        // how many bytes of RAM you want to allocate for data buffers
unsigned int8 data[BUFF_SIZE];

#include <w5200.c>

void main() {

  output_high(W5200_CS);
  setup_spi(SPI_MASTER | SPI_MODE_3 | SPI_CLK_DIV_16);

  w5200_init();

 // I had an external EEPROM MAC in my h/w (microchip part). For dummy work, set something here like:

  mac_addr[0] = 0xC0;
  mac_addr[1] = 0xFF;
  mac_addr[2] = 0xEE;
  mac_addr[3] = 0xF0;
  mac_addr[4] = 0x0F;
  mac_addr[5] = 0xF0;

 // dunno if that'll work. borrow a mac address off a defunct network card or something else NOT on your network

  w5200_set_mac();
  w5200_set_ip(192, 168, 225, 225);
  w5200_set_gw(192, 168, 225, 1);
  w5200_set_subnet(255, 255, 255, 0);

  while(true) {
  // do something useful. This repeatedly spawns a UDP ECHO server
    open_udp_socket(0, 7);    // open a UDP socket on socket 0, port 7 to listen
    udp_echo_server();          // service the socket
  }
}


Hopefully this helps someone. Enjoy.

** edit to add "data" used in UDP echo server example and #define the data buffer size (#define BUFF_SIZE).


-Patrick
thefloyd



Joined: 02 Sep 2009
Posts: 46

View user's profile Send private message

W5200 / wiz820io TCP routine
PostPosted: Sat Dec 24, 2016 12:56 pm     Reply with quote

To add to the above, here's routines to open a TCP socket and open it, print a banner upon connection, listen on it for data, and write the data out to the first serial port. Works the same as the udp example - you open a tcp socket with socknum (0-7) and port number using open_tcp_socket and then call ReceiveTCPData to read it. Looks like I made assumptions about socket numbers - the latter routine seems to have sock0 registers hard coded, so you'd need to change that if you needed to use a socket other than 0. The W5200 supports 8 simultaneous sockets, and I've defined 0, 1, and 7 in the w5200.h file given (it's trivial to define the ones in the middle, too, I just didn't need them).

Code:

void open_tcp_socket(unsigned int16 socknum, unsigned int16 portnum) {
  socknum *= 0x0100;
  do {
    write_reg((SOCK_MR + socknum), S_MR_TCP);
    write_reg((SOCK_PORT0 + socknum), (portnum >> 8));
    write_reg((SOCK_PORT1 + socknum), portnum);
    write_reg((SOCK_CR + socknum), S_CR_OPEN);
    if(read_reg(SOCK_SR + socknum) != SOCK_INIT) {
      write_reg((SOCK_CR + socknum), S_CR_CLOSE);
    }
    write_reg((SOCK_CR + socknum), S_CR_LISTEN);
  } while(read_reg(SOCK_SR + socknum) != SOCK_LISTEN);
}

unsigned int ReceiveTCPData() {
  unsigned int8 size, status;
  unsigned int16 i16, get_size, offset, start_addr, wr_reg, ptr;
  char banner[31] = "\r\n\r\nW5200 test. Enter command:";

  if(w5200_read_reg(S0_SR) != SOCK_ESTABLISHED) return(0);
  printf("Socket ESTABLISHED..\r\n");

  wr_reg = w5200_read_reg(S0_TX_WR0);
  wr_reg = (wr_reg << 8) + w5200_read_reg(S0_TX_WR1);
  offset = wr_reg & gS0_TX_MASK;
  start_addr = gS0_TX_BASE + offset;
  size = strlen16(banner);
  w5200_burst_write(start_addr, banner, size);
  ptr = wr_reg + size;
  w5200_write_reg(S0_TX_WR0,(ptr >> 8));
  w5200_write_reg(S0_TX_WR1, ptr);
  w5200_write_reg(S0_CR, S_CR_SEND);
  do {
    status = w5200_read_reg(S0_IR);
    printf("Waiting (tx)..\r\n");
  } while (!bit_test(status, 4));
  do {
    get_size = w5200_read_reg(S0_RX_RSR0);
    get_size = ( get_size << 8 ) + w5200_read_reg(S0_RX_RSR1);
    status = w5200_read_reg(S0_SR);
  } while ((get_size == 0x0000) && (status != SOCK_CLOSE_WAIT));
  if(status == SOCK_CLOSE_WAIT) {
    w5200_write_reg(S0_CR,S_CR_DISCON);
    printf("Socket disconnected..\r\n");
    return(1);
  }
//  if(get_size > BUFF_SIZE) get_size = BUFF_SIZE;     // don't allow buffer overruns - (20161223) not needed here since we're not stashing data into internal memory, rather reading directly from the w5200 chip in burst mode and dumping the data out to the serial console), but don't forget to re-enable this if you start reading into internal PIC RAM
  ptr = w5200_read_reg(S0_RX_RD0);
  ptr = ( ptr << 8 ) + w5200_read_reg(S0_RX_RD1);
  offset =  ptr & gS0_RX_MASK;                         // masked rx pointer
  start_addr = gS0_RX_BASE + offset;      // real rx pointer
  w5200_burst_read(start_addr, data, get_size);
  for(i16=0;i16<get_size;i16++) {
    printf("%c", data[i16]);
  }
  printf("\r\n");
  ptr = ptr + get_size;
  w5200_write_reg(S0_RX_RD0, (ptr >> 8));
  w5200_write_reg(S0_RX_RD1, ptr);
  w5200_write_reg(S0_CR,S_CR_RECV);
  while(w5200_read_reg(S0_CR) != 0x00) { }
  w5200_write_reg(S0_CR,S_CR_DISCON);
  w5200_write_reg(S0_CR,S_CR_CLOSE);
  printf("Socket disconnected..\r\n");
  return(1);
}
thefloyd



Joined: 02 Sep 2009
Posts: 46

View user's profile Send private message

finally...
PostPosted: Sat Dec 24, 2016 1:03 pm     Reply with quote

Finally, as you can see I was in the process of converting the routines to programmatically derive the socket register locations and not be dependent on hard coded S0 through S7 values in the w5200.h file. The routines to setup the udp/tcp socket use them, the example echo server and TCP server routines unfortunately don't. The former are from my later work with the chip and the latter are from my early work where I was literally just reading the data sheet and trying to make usable code.

As I said - there's huge opportunity to clean this up a little and take it further and make it a usable w5200 library for CCS C but I just haven't had the time. I'm still cracking on in the background but wanted to share this work anyway.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group