123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561 |
- /*
- * Wiznet5500 library
- * Contains functions to allow for networking
- *
- * Functions from this library can be used to operate up to 8 sockets
- * Application based code should not be in this library
- */
- // uses stdlib.c
- // Wiznet W5500 Op Codes
- #define WIZNET_WRITE_COMMON 0x04 //opcode to write to one of the common block of registers
- #define WIZNET_READ_COMMON 0x00 //opcode to read one of the common block of registers
- #define WIZNET_WRITE_SnR 0x0C // s<<5 (nnn 01 1 00) opcode to write to one of the socket n registers
- #define WIZNET_READ_SnR 0x08 // s<<5 (nnn 01 0 00) opcode to read one of the socket n registers
- #define WIZNET_WRITE_SnTX 0x14 // s<<5 (nnn 10 1 00) opcode to write to the socket n transmit buffer
- #define WIZNET_READ_SnRX 0x18 // s<<5 (nnn 11 0 00) opcode to read from the socket n receive buffer
- // Wiznet W5500 Register Addresses
- #define WIZNET_MR 0x0000 // Mode
- #define WIZNET_GAR 0x0001 // Gateway IP address
- #define WIZNET_SUBR 0x0005 // Subnet mask address
- #define WIZNET_SHAR 0x0009 // Source MAC address
- #define WIZNET_SIPR 0x000F // Source IP address
- #define WIZNET_IR 0x0015 // Interrupt
- #define WIZNET_IMR 0x0016 // Interrupt Mask
- #define WIZNET_RTR 0x0019 // Timeout address
- #define WIZNET_RCR 0x001B // Retry count
- #define WIZNET_UIPR 0x0028 // Unreachable IP address in UDP mode
- #define WIZNET_UPORT 0x002C // Unreachable Port address in UDP mode
- //W5500 Socket Registers follow
- #define WIZNET_SnMR 0x0000 // Mode
- #define WIZNET_SnCR 0x0001 // Command
- #define WIZNET_SnIR 0x0002 // Interrupt
- #define WIZNET_SnSR 0x0003 // Status
- #define WIZNET_SnPORT 0x0004 // Source Port (2 bytes)
- #define WIZNET_SnDHAR 0x0006 // Destination Hardw Addr
- #define WIZNET_SnDIPR 0x000C // Destination IP Addr
- #define WIZNET_SnDPORT 0x0010 // Destination Port
- #define WIZNET_SnMSSR 0x0012 // Max Segment Size
- #define WIZNET_SnPROTO 0x0014 // Protocol in IP RAW Mode
- #define WIZNET_SnTOS 0x0015 // IP TOS
- #define WIZNET_SnTTL 0x0016 // IP TTL
- #define WIZNET_SnRX_BSZ 0x001E // RX Buffer Size
- #define WIZNET_SnTX_BSZ 0x001F // TX Buffer Size
- #define WIZNET_SnTX_FSR 0x0020 // TX Free Size
- #define WIZNET_SnTX_RD 0x0022 // TX Read Pointer
- #define WIZNET_SnTX_WR 0x0024 // TX Write Pointer
- #define WIZNET_SnRX_RSR 0x0026 // RX RECEIVED SIZE REGISTER
- #define WIZNET_SnRX_RD 0x0028 // RX Read Pointer
- #define WIZNET_SnRX_WR 0x002A // RX Write Pointer (supported?
- //Socket n Mode Register (0x0000)
- //WIZNET_SnMR
- #define WIZNET_MR_CLOSE 0x00 // Unused socket
- #define WIZNET_MR_TCP 0x01 // TCP
- #define WIZNET_MR_UDP 0x02 // UDP
- #define WIZNET_MR_IPRAW 0x03 // IP LAYER RAW SOCK
- #define WIZNET_MR_MACRAW 0x04 // MAC LAYER RAW SOCK
- #define WIZNET_MR_PPPOE 0x05 // PPPoE
- #define WIZNET_MR_ND 0x20 // No Delayed Ack(TCP) flag
- #define WIZNET_MR_MULTI 0x80 // support multicating
- //Socket n Command Register (0x0001)
- //WIZNET_SnCR
- #define WIZNET_CR_OPEN 0x01 // Initialize or open socket
- #define WIZNET_CR_LISTEN 0x02 // Wait connection request in tcp mode(Server mode)
- #define WIZNET_CR_CONNECT 0x04 // Send connection request in tcp mode(Client mode)
- #define WIZNET_CR_DISCON 0x08 // Send closing reqeuset in tcp mode
- #define WIZNET_CR_CLOSE 0x10 // Close socket
- #define WIZNET_CR_SEND 0x20 // Update Tx memory pointer and send data
- #define WIZNET_CR_SEND_MAC 0x21 // Send data with MAC address, so without ARP process
- #define WIZNET_CR_SEND_KEEP 0x22 // Send keep alive message
- #define WIZNET_CR_RECV 0x40 // Update Rx memory buffer pointer and receive data
- //Socket n Interrupt Register (0x0002)
- //WIZNET_SnIR
- // Bit 0: CON
- // Bit 1: DISCON
- // Bit 2: RECV
- // Bit 3: TIMEOUT
- // Bit 4: SEND_OK
- //Socket n Status Register (0x0003)
- //WIZNET_SnSR
- #define WIZNET_SOCK_CLOSED 0x00 // Closed
- #define WIZNET_SOCK_INIT 0x13 // Init state
- #define WIZNET_SOCK_LISTEN 0x14 // Listen state
- #define WIZNET_SOCK_SYNSENT 0x15 // Connection state
- #define WIZNET_SOCK_SYNRECV 0x16 // Connection state
- #define WIZNET_SOCK_ESTABLISHED 0x17 // Success to connect
- #define WIZNET_SOCK_FIN_WAIT 0x18 // Closing state
- #define WIZNET_SOCK_CLOSING 0x1A // Closing state
- #define WIZNET_SOCK_TIME_WAIT 0x1B // Closing state
- #define WIZNET_SOCK_CLOSE_WAIT 0x1C // Closing state
- #define WIZNET_SOCK_LAST_ACK 0x1D // Closing state
- #define WIZNET_SOCK_UDP 0x22 // UDP socket
- #define WIZNET_SOCK_IPRAW 0x32 // IP raw mode socket
- #define WIZNET_SOCK_MACRAW 0x42 // MAC raw mode socket
- #define WIZNET_SOCK_PPPOE 0x5F // PPPOE socket
- //Socket n Source Port Register (0x0004, 0x0005)
- //WIZNET_SnPORT
- // MSByte: 0x0004
- // LSByte: 0x0005
- #define WIZNET_MAX_RBUF 2048 // buffer for receiving data (max rx packet size!)
- #define WIZNET_MAX_TBUF 2048 // buffer for sending data (max tx packet size!)
- //-------------------
- //BASIC READ AND WRITE FUNCTIONS
- //-------------------
- // Sets SPI3_CS low
- void WizSpiBeginTransfer()
- {
- asm(
- "; backup regs\n"
- "push r1\n"
- "push r2\n"
- "load32 0xC02732 r2 ; r2 = 0xC02732\n"
- "load 0 r1 ; r1 = 0 (enable)\n"
- "write 0 r2 r1 ; write to SPI3_CS\n"
- "; restore regs\n"
- "pop r2\n"
- "pop r1\n"
- );
- }
- // Sets SPI3_CS high
- void WizSpiEndTransfer()
- {
- asm(
- "; backup regs\n"
- "push r1\n"
- "push r2\n"
- "load32 0xC02732 r2 ; r2 = 0xC02732\n"
- "load 1 r1 ; r1 = 1 (disable)\n"
- "write 0 r2 r1 ; write to SPI3_CS\n"
- "; restore regs\n"
- "pop r2\n"
- "pop r1\n"
- );
- }
- // write dataByte and return read value
- // write 0x00 for a read
- // Writes byte over SPI3 to W5500
- word WizSpiTransfer(word dataByte)
- {
- word retval = 0;
- asm(
- "load32 0xC02731 r2 ; r2 = 0xC02731\n"
- "write 0 r2 r4 ; write r4 over SPI3\n"
- "read 0 r2 r2 ; read return value\n"
- "write -4 r14 r2 ; write to stack to return\n"
- );
- return retval;
- }
- // Write data to W5500
- void wizWrite(word addr, word cb, char* buf, word len)
- {
- WizSpiBeginTransfer();
- // Send address
- word addrMSB = (unsigned) addr >> 8;
- WizSpiTransfer(addrMSB); //msByte
- WizSpiTransfer(addr); //lsByte
- // Send control byte
- WizSpiTransfer(cb);
- // Send data
- word i;
- for (i = 0; i < len; i++)
- {
- WizSpiTransfer(buf[i]);
- }
- WizSpiEndTransfer();
- }
- // Write single byte to W5500
- word wizWriteSingle(word addr, word cb, word data)
- {
- WizSpiBeginTransfer();
- // Send address
- word addrMSB = (unsigned) addr >> 8;
- WizSpiTransfer(addrMSB); //msByte
- WizSpiTransfer(addr); //lsByte
- // Send control byte
- WizSpiTransfer(cb);
- // Send data
- WizSpiTransfer(data);
- WizSpiEndTransfer();
- return data;
- }
- // Write two bytes to W5500
- void wizWriteDouble(word addr, word cb, word data)
- {
- WizSpiBeginTransfer();
- // Send address
- word addrMSB = (unsigned) addr >> 8;
- WizSpiTransfer(addrMSB); //msByte
- WizSpiTransfer(addr); //lsByte
- // Send control byte
- WizSpiTransfer(cb);
- // Send data
- word dataMSB = (unsigned) data >> 8;
- WizSpiTransfer(dataMSB);
- WizSpiTransfer(data);
- WizSpiEndTransfer();
- }
- void wizRead(word addr, word cb, char* buf, word len)
- {
- WizSpiBeginTransfer();
- // Send address
- word addrMSB = (unsigned) addr >> 8;
- WizSpiTransfer(addrMSB); //msByte
- WizSpiTransfer(addr); //lsByte
- // Send control byte
- WizSpiTransfer(cb);
- // Read data
- word i;
- for (i = 0; i < len; i++)
- {
- buf[i] = WizSpiTransfer(0);
- }
- WizSpiEndTransfer();
- }
- word wizReadSingle(word addr, word cb)
- {
- WizSpiBeginTransfer();
- // Send address
- word addrMSB = (unsigned) addr >> 8;
- WizSpiTransfer(addrMSB); //msByte
- WizSpiTransfer(addr); //lsByte
- // Send control byte
- WizSpiTransfer(cb);
- // Read data
- word retval = WizSpiTransfer(0);
- WizSpiEndTransfer();
- // Return read value
- return retval;
- }
- word wizReadDouble(word addr, word cb)
- {
- WizSpiBeginTransfer();
- // Send address
- word addrMSB = (unsigned) addr >> 8;
- WizSpiTransfer(addrMSB); //msByte
- WizSpiTransfer(addr); //lsByte
- // Send control byte
- WizSpiTransfer(cb);
- // Read data
- word retval = WizSpiTransfer(0) << 8;
- retval = retval + WizSpiTransfer(0);
- WizSpiEndTransfer();
- // Return read value
- return retval;
- }
- //-------------------
- //W5500 SOCKET REGISTER FUNCTIONS
- //-------------------
- // Send a command cmd to socket s
- void wizCmd(word s, word cmd)
- {
- //wizWriteSingle(WIZNET_SnCR, WIZNET_WRITE_SnR, cmd);
- WizSpiBeginTransfer();
- WizSpiTransfer(0); //msByte
- WizSpiTransfer(WIZNET_SnCR); //lsByte
- WizSpiTransfer(WIZNET_WRITE_SnR + (s << 5));
- WizSpiTransfer(cmd);
- WizSpiEndTransfer();
- // wait untill done
- while ( wizReadSingle(WIZNET_SnCR, WIZNET_READ_SnR) );
- }
- // Write 8 bits to a sockets control register
- void wizSetSockReg8(word s, word addr, word val)
- {
- //wizWriteSingle(addr, WIZNET_WRITE_SnR, val);
- WizSpiBeginTransfer();
- WizSpiTransfer(0); //msByte
- WizSpiTransfer(addr); //lsByte
- WizSpiTransfer(WIZNET_WRITE_SnR + (s << 5));
- WizSpiTransfer(val);
- WizSpiEndTransfer();
- }
- // Read 8 bits from a sockets control register
- word wizGetSockReg8(word s, word addr){
- //return wizReadSingle(addr, WIZNET_READ_SnR);
- WizSpiBeginTransfer();
- // Send address
- word addrMSB = (unsigned) addr >> 8;
- WizSpiTransfer(addrMSB); //msByte
- WizSpiTransfer(addr); //lsByte
- word cb = WIZNET_READ_SnR + (s << 5);
-
- // Send control byte
- WizSpiTransfer(cb);
- // Read data
- word retval = WizSpiTransfer(0);
- WizSpiEndTransfer();
- // Return read value
- return retval;
- }
- // Write 16 bits to a sockets control register
- void wizSetSockReg16(word s, word addr, word val)
- {
- //wizWriteDouble(addr, WIZNET_WRITE_SnR + (s << 5), val);
- WizSpiBeginTransfer();
- WizSpiTransfer(0); //msByte
- WizSpiTransfer(addr); //lsByte
- WizSpiTransfer(WIZNET_WRITE_SnR + (s << 5));
- word valMSB = (unsigned) val >> 8;
- WizSpiTransfer(valMSB);
- WizSpiTransfer(val);
- WizSpiEndTransfer();
- }
- // Read 16 bits from a sockets control register
- word wizGetSockReg16(word s, word addr)
- {
- //return wizReadDouble(addr, WIZNET_READ_SnR + (s << 5));
- WizSpiBeginTransfer();
- // Send address
- word addrMSB = (unsigned) addr >> 8;
- WizSpiTransfer(addrMSB); //msByte
- WizSpiTransfer(addr); //lsByte
- word cb = WIZNET_READ_SnR + (s << 5);
- // Send control byte
- WizSpiTransfer(cb);
- // Read data
- word retval = WizSpiTransfer(0) << 8;
- retval = retval + WizSpiTransfer(0);
- WizSpiEndTransfer();
- // Return read value
- return retval;
- }
- //-------------------
- //W5500 SETUP FUNCTIONS
- //-------------------
- // Initialize W5500 chip
- void wiz_Init(char* ip_addr, char* gateway_addr, char* mac_addr, char* sub_mask)
- {
- WizSpiEndTransfer();
- delay(10);
- wizWrite(WIZNET_SIPR, WIZNET_WRITE_COMMON, ip_addr, 4);
- wizWrite(WIZNET_GAR, WIZNET_WRITE_COMMON, gateway_addr, 4);
- wizWrite(WIZNET_SHAR, WIZNET_WRITE_COMMON, mac_addr, 6);
- wizWrite(WIZNET_SUBR, WIZNET_WRITE_COMMON, sub_mask, 4);
- }
- // Initialize socket s for TCP
- void wizInitSocketTCP(word s, word port)
- {
- wizCmd(s, WIZNET_CR_CLOSE);
- wizSetSockReg8 (s, WIZNET_SnIR, 0xFF); //reset interrupt register
- wizSetSockReg8 (s, WIZNET_SnMR, WIZNET_MR_TCP); //set mode register to tcp
- wizSetSockReg16 (s, WIZNET_SnPORT, port); //set tcp port
- wizCmd(s, WIZNET_CR_OPEN);
- wizCmd(s, WIZNET_CR_LISTEN);
- delay(10); //wait a bit to make sure the socket is in the correct state (technically not necessary)
- }
- // Initialize socket s for TCP client
- void wizInitSocketTCPClient(word s, word port)
- {
- wizCmd(s, WIZNET_CR_CLOSE);
- wizSetSockReg8 (s, WIZNET_SnIR, 0xFF); //reset interrupt register
- wizSetSockReg8 (s, WIZNET_SnMR, WIZNET_MR_TCP); //set mode register to tcp
- wizSetSockReg16 (s, WIZNET_SnPORT, port); //set tcp port
- wizCmd(s, WIZNET_CR_OPEN);
- delay(10); //wait a bit to make sure the socket is in the correct state (technically not necessary)
- }
- //-------------------
- //W5500 READING AND WRITING FUNCTIONS
- //-------------------
- // from memory, so no need for unsigned comparisons (because we have less than 2GB RAM)
- word wizWriteDataFromMemory(word s, char* buf, word buflen)
- {
- // Make sure there is something to send
- if (buflen <= 0)
- {
- return 0;
- }
- word bytesSent = 0;
- // loop until all bytes are sent
- while (bytesSent != buflen)
- {
- if (wizGetSockReg8(s, WIZNET_SnSR) == WIZNET_SOCK_CLOSED)
- {
- //uprintln("connection closed");
- return 0;
- }
- word partToSend = buflen - bytesSent;
- if (partToSend > WIZNET_MAX_TBUF)
- partToSend = WIZNET_MAX_TBUF;
- // Make sure there is room in the transmit buffer for what we want to send
- word txfree = wizGetSockReg16(s, WIZNET_SnTX_FSR); // Size of the available buffer area
- word timeout = 0;
- while (txfree < partToSend)
- {
- timeout++; // Increase timeout counter
- delay(1); // Wait a bit
- txfree = wizGetSockReg16(s, WIZNET_SnTX_FSR); // Size of the available buffer area
-
- // After a second
- if (timeout > 1000)
- {
- wizCmd(s, WIZNET_CR_DISCON); // Disconnect the connection
- //uprintln("timeout");
- return 0;
- }
- }
- // Space is available so we will send the buffer
- word txwr = wizGetSockReg16(s, WIZNET_SnTX_WR); // Read the Tx Write Pointer
- // Write the outgoing data to the transmit buffer
- wizWrite(txwr, WIZNET_WRITE_SnTX + (s << 5), buf + bytesSent, partToSend);
- // update the buffer pointer
- word newSize = txwr + partToSend;
- wizSetSockReg16(s, WIZNET_SnTX_WR, newSize);
- // Now Send the SEND command which tells the wiznet the pointer is updated
- wizCmd(s, WIZNET_CR_SEND);
- // Update the amount of bytes sent
- bytesSent += partToSend;
- }
- return 1;
- }
- // Read received data
- word wizReadRecvData(word s, char* buf, word buflen)
- {
- if (buflen == 0)
- {
- return 1;
- }
-
- if (buflen > WIZNET_MAX_RBUF) // If the request size > WIZNET_MAX_RBUF, truncate it to prevent overflow
- {
- //uprintln("W: Received too large TCP data");
- buflen = WIZNET_MAX_RBUF; // - 1; // -1 Because room for 0 terminator
- }
-
- // Get the address where the wiznet is holding the data
- word rxrd = wizGetSockReg16(s, WIZNET_SnRX_RD);
- // Read the data into the buffer
- wizRead(rxrd, WIZNET_READ_SnRX + (s << 5), buf, buflen);
- // Remove read data from rxbuffer to make space for new data
- word nsize = rxrd + buflen;
- wizSetSockReg16(s, WIZNET_SnRX_RD, nsize); //replace read data pointer
- //tell the wiznet we have retrieved the data
- wizCmd(s, WIZNET_CR_RECV);
- // Terminate buffer for printing in case the data was a string
- *(buf + buflen) = 0;
- return 1;
- }
- // Remove the received data
- void wizFlush(word s, word rsize)
- {
- if (rsize > 0)
- {
- word rxrd = wizGetSockReg16(s, WIZNET_SnRX_RD); //retrieve read data pointer
- word nsize = rxrd + rsize;
- wizSetSockReg16(s, WIZNET_SnRX_RD, nsize); //replace read data pointer
- //tell the wiznet we have retrieved the data
- wizCmd(s, WIZNET_CR_RECV);
- }
- }
|