WIZNet W5500 with additional enhancements

Fork of WIZnetInterface by WIZnet

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers W5500.cpp Source File

W5500.cpp

00001 /* Copyright (C) 2012 mbed.org, MIT License
00002  *
00003  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004  * and associated documentation files (the "Software"), to deal in the Software without restriction,
00005  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
00006  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00007  * furnished to do so, subject to the following conditions:
00008  *
00009  * The above copyright notice and this permission notice shall be included in all copies or
00010  * substantial portions of the Software.
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017  */
00018 #include "eth_arch.h"
00019 #if (not defined TARGET_WIZwiki_W7500) && (not defined TARGET_WIZwiki_W7500P) && (not defined TARGET_WIZwiki_W7500ECO)
00020 
00021 
00022 
00023 #include "mbed.h"
00024 #include "mbed_debug.h"
00025 #include "DNSClient.h"
00026 
00027 
00028 //Debug is disabled by default
00029 #if 0
00030 #define DBG(...) do{debug("%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); debug(__VA_ARGS__); } while(0);
00031 //#define DBG(x, ...) debug("[W5500:DBG]"x"\r\n", ##__VA_ARGS__);
00032 #define WARN(x, ...) debug("[W5500:WARN]"x"\r\n", ##__VA_ARGS__);
00033 #define ERR(x, ...) debug("[W5500:ERR]"x"\r\n", ##__VA_ARGS__);
00034 #else
00035 #define DBG(x, ...)
00036 #define WARN(x, ...)
00037 #define ERR(x, ...)
00038 #endif
00039 
00040 #if 1
00041 #define INFO(x, ...) debug("[W5500:INFO]"x"\r\n", ##__VA_ARGS__);
00042 #else
00043 #define INFO(x, ...)
00044 #endif
00045 
00046 #define DBG_SPI 0
00047 
00048 WIZnet_Chip* WIZnet_Chip::inst;
00049 
00050 WIZnet_Chip::WIZnet_Chip(PinName mosi, PinName miso, PinName sclk, PinName _cs, PinName _reset):
00051     cs(_cs), reset_pin(_reset)
00052 {
00053     spi = new SPI(mosi, miso, sclk);
00054     cs = 1;
00055     reset_pin = 1;
00056     inst = this;
00057     dnsaddr = 0;
00058     timesrv = 0;
00059     leaseTime = 0;
00060     sock_any_port = SOCK_ANY_PORT_NUM;
00061 }
00062 
00063 WIZnet_Chip::WIZnet_Chip(SPI* spi, PinName _cs, PinName _reset):
00064     cs(_cs), reset_pin(_reset)
00065 {
00066     this->spi = spi;
00067     cs = 1;
00068     reset_pin = 1;
00069     inst = this;
00070     sock_any_port = SOCK_ANY_PORT_NUM;
00071 }
00072 
00073 bool WIZnet_Chip::setmac()
00074 {
00075 
00076     for (int i =0; i < 6; i++) reg_wr<uint8_t>(SHAR+i, mac[i]);
00077 
00078     return true;
00079 }
00080 
00081 // Set the IP
00082 bool WIZnet_Chip::setip()
00083 {
00084     reg_wr<uint32_t>(SIPR, ip);
00085     reg_wr<uint32_t>(GAR, gateway);
00086     reg_wr<uint32_t>(SUBR, netmask);
00087     return true;
00088 }
00089 
00090 bool WIZnet_Chip::setProtocol(int socket, Protocol p)
00091 {
00092     if (socket < 0) {
00093         return false;
00094     }
00095     sreg<uint8_t>(socket, Sn_MR, p);
00096     return true;
00097 }
00098 
00099 bool WIZnet_Chip::connect(int socket, const char * host, int port, int timeout_ms)
00100 {
00101     if (socket < 0) {
00102         return false;
00103     }
00104     sreg<uint8_t>(socket, Sn_MR, TCP);
00105     scmd(socket, OPEN);
00106     sreg_ip(socket, Sn_DIPR, host);
00107     sreg<uint16_t>(socket, Sn_DPORT, port);
00108     sreg<uint16_t>(socket, Sn_PORT, new_port());
00109     scmd(socket, CONNECT);
00110     Timer t;
00111     t.reset();
00112     t.start();
00113     while(!is_connected(socket)) {
00114         if (t.read_ms() > timeout_ms) {
00115             return false;
00116         }
00117     }
00118     return true;
00119 }
00120 
00121 bool WIZnet_Chip::gethostbyname(const char* host, uint32_t* ip)
00122 {
00123     uint32_t addr = str_to_ip(host);
00124     char buf[17];
00125     snprintf(buf, sizeof(buf), "%d.%d.%d.%d", (int)(addr>>24)&0xff, (int)(addr>>16)&0xff, (int)(addr>>8)&0xff, (int)addr&0xff);
00126     if (strcmp(buf, host) == 0) {
00127         *ip = addr;
00128         return true;
00129     }
00130     DNSClient client;
00131     if(client.lookup(host, dnsaddr)) {
00132         *ip = client.ip;
00133         return true;
00134     }
00135     return false;
00136 }
00137 
00138 bool WIZnet_Chip::disconnect()
00139 {
00140     return true;
00141 }
00142 
00143 bool WIZnet_Chip::is_connected(int socket)
00144 {
00145     /*
00146         if (sreg<uint8_t>(socket, Sn_SR) == SOCK_ESTABLISHED) {
00147             return true;
00148         }
00149     */
00150     uint8_t tmpSn_SR;
00151     tmpSn_SR = sreg<uint8_t>(socket, Sn_SR);
00152     // packet sending is possible, when state is SOCK_CLOSE_WAIT.
00153     if ((tmpSn_SR == SOCK_ESTABLISHED) || (tmpSn_SR == SOCK_CLOSE_WAIT)) {
00154         return true;
00155     }
00156     return false;
00157 }
00158 
00159 // Reset the chip & set the buffer
00160 void WIZnet_Chip::reset()
00161 {
00162 #if defined(USE_WIZ550IO_MAC)
00163     //read the MAC address inside the module    
00164     reg_rd_mac(SHAR, mac); 
00165 #endif
00166     // hw reset
00167     reset_pin = 1;
00168     reset_pin = 0;
00169     setMR(1<<7); // soft reset the hardware reset is connected.
00170     wait_us(500); // 500us (w5500)
00171     reset_pin = 1;
00172     wait_ms(400); // 400ms (w5500)
00173 #if defined(USE_WIZ550IO_MAC)
00174     // write MAC address inside the WZTOE MAC address register
00175     reg_wr_mac(SHAR, mac);
00176 #endif
00177     // set RX and TX buffer size
00178 #if 0
00179     for (int socket = 0; socket < MAX_SOCK_NUM; socket++) {
00180         sreg<uint8_t>(socket, Sn_RXBUF_SIZE, 2);
00181         sreg<uint8_t>(socket, Sn_TXBUF_SIZE, 2);
00182     }
00183 #endif
00184 }
00185 
00186 
00187 bool WIZnet_Chip::close(int socket)
00188 {
00189     if (socket < 0) {
00190         return false;
00191     }
00192     // if not connected, return
00193     if (sreg<uint8_t>(socket, Sn_SR) == SOCK_CLOSED) {
00194         return true;
00195     }
00196     if (sreg<uint8_t>(socket, Sn_MR) == TCP) {
00197         scmd(socket, DISCON);
00198     }
00199     scmd(socket, CLOSE);
00200     sreg<uint8_t>(socket, Sn_IR, 0xff);
00201     return true;
00202 }
00203 
00204 int WIZnet_Chip::wait_readable(int socket, int wait_time_ms, int req_size)
00205 {
00206     if (socket < 0) {
00207         return -1;
00208     }
00209     Timer t;
00210     t.reset();
00211     t.start();
00212     while(1) {
00213         //int size = sreg<uint16_t>(socket, Sn_RX_RSR);
00214         // during the reading Sn_RX_RXR, it has the possible change of this register.
00215         // so read twice and get same value then use size information.
00216         int size, size2;
00217         do {
00218             size = sreg<uint16_t>(socket, Sn_RX_RSR);
00219             size2 = sreg<uint16_t>(socket, Sn_RX_RSR);
00220         } while (size != size2);
00221         
00222         if (size > req_size) {
00223             return size;
00224         }
00225         if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
00226             break;
00227         }
00228     }
00229     return -1;
00230 }
00231 
00232 int WIZnet_Chip::wait_writeable(int socket, int wait_time_ms, int req_size)
00233 {
00234     if (socket < 0) {
00235         return -1;
00236     }
00237     Timer t;
00238     t.reset();
00239     t.start();
00240     while(1) {
00241         //int size = sreg<uint16_t>(socket, Sn_TX_FSR);
00242         // during the reading Sn_TX_FSR, it has the possible change of this register.
00243         // so read twice and get same value then use size information.
00244         int size, size2;
00245         do {
00246             size = sreg<uint16_t>(socket, Sn_TX_FSR);
00247             size2 = sreg<uint16_t>(socket, Sn_TX_FSR);
00248         } while (size != size2);
00249         
00250         if (size > req_size) {
00251             return size;
00252         }
00253         if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
00254             break;
00255         }
00256     }
00257     return -1;
00258 }
00259 
00260 int WIZnet_Chip::send(int socket, const char * str, int len)
00261 {
00262     if (socket < 0) {
00263         return -1;
00264     }
00265     uint16_t ptr = sreg<uint16_t>(socket, Sn_TX_WR);
00266     uint8_t cntl_byte = (0x14 + (socket << 5));
00267     spi_write(ptr, cntl_byte, (uint8_t*)str, len);
00268     sreg<uint16_t>(socket, Sn_TX_WR, ptr + len);
00269     scmd(socket, SEND);
00270     uint8_t tmp_Sn_IR;
00271     while (( (tmp_Sn_IR = sreg<uint8_t>(socket, Sn_IR)) & INT_SEND_OK) != INT_SEND_OK) {
00272         // @Jul.10, 2014 fix contant name, and udp sendto function.
00273         switch (sreg<uint8_t>(socket, Sn_SR)) {
00274             case SOCK_CLOSED :
00275                 close(socket);
00276                 return 0;
00277                 //break;
00278             case SOCK_UDP :
00279                 // ARP timeout is possible.
00280                 if ((tmp_Sn_IR & INT_TIMEOUT) == INT_TIMEOUT) {
00281                     sreg<uint8_t>(socket, Sn_IR, INT_TIMEOUT);
00282                     return 0;
00283                 }
00284                 break;
00285             default :
00286                 break;
00287         }
00288     }
00289     /*
00290         while ((sreg<uint8_t>(socket, Sn_IR) & INT_SEND_OK) != INT_SEND_OK) {
00291             if (sreg<uint8_t>(socket, Sn_SR) == CLOSED) {
00292                 close(socket);
00293                 return 0;
00294             }
00295         }
00296     */
00297     sreg<uint8_t>(socket, Sn_IR, INT_SEND_OK);
00298 
00299     return len;
00300 }
00301 
00302 int WIZnet_Chip::recv(int socket, char* buf, int len)
00303 {
00304     if (socket < 0) {
00305         return -1;
00306     }
00307     uint16_t ptr = sreg<uint16_t>(socket, Sn_RX_RD);
00308     uint8_t cntl_byte = (0x18 + (socket << 5));
00309     spi_read(ptr, cntl_byte, (uint8_t*)buf, len);
00310     sreg<uint16_t>(socket, Sn_RX_RD, ptr + len);
00311     scmd(socket, RECV);
00312     return len;
00313 }
00314 
00315 int WIZnet_Chip::new_socket()
00316 {
00317     for(int s = 0; s < MAX_SOCK_NUM; s++) {
00318         if (sreg<uint8_t>(s, Sn_SR) == SOCK_CLOSED) {
00319             return s;
00320         }
00321     }
00322     return -1;
00323 }
00324 
00325 uint16_t WIZnet_Chip::new_port()
00326 {
00327     uint16_t port = rand();
00328     port |= 49152;
00329     return port;
00330 }
00331 
00332 bool WIZnet_Chip::link(int wait_time_ms)
00333 {
00334     Timer t;
00335     t.reset();
00336     t.start();
00337     while(1) {
00338         int is_link = ethernet_link();
00339         
00340         if (is_link) {
00341             return true;
00342         }
00343         if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
00344             break;
00345         }
00346     }
00347     return 0;
00348 }
00349 
00350 void WIZnet_Chip::set_link(PHYMode phymode)
00351 {
00352     int speed = -1;
00353     int duplex = 0;
00354 
00355     switch(phymode) {
00356         case AutoNegotiate : speed = -1; duplex = 0; break;
00357         case HalfDuplex10  : speed = 0;  duplex = 0; break;
00358         case FullDuplex10  : speed = 0;  duplex = 1; break;
00359         case HalfDuplex100 : speed = 1;  duplex = 0; break;
00360         case FullDuplex100 : speed = 1;  duplex = 1; break;
00361     }
00362 
00363     ethernet_set_link(speed, duplex);
00364 }
00365 
00366 void WIZnet_Chip::scmd(int socket, Command cmd)
00367 {
00368     sreg<uint8_t>(socket, Sn_CR, cmd);
00369     while(sreg<uint8_t>(socket, Sn_CR));
00370 }
00371 
00372 void WIZnet_Chip::spi_write(uint16_t addr, uint8_t cb, const uint8_t *buf, uint16_t len)
00373 {
00374     cs = 0;
00375     spi->write(addr >> 8);
00376     spi->write(addr & 0xff);
00377     spi->write(cb);
00378     for(int i = 0; i < len; i++) {
00379         spi->write(buf[i]);
00380     }
00381     cs = 1;
00382 
00383 #if DBG_SPI 
00384     debug("[SPI]W %04x(%02x %d)", addr, cb, len);
00385     for(int i = 0; i < len; i++) {
00386         debug(" %02x", buf[i]);
00387         if (i > 16) {
00388             debug(" ...");
00389             break;
00390         }
00391     }
00392     debug("\r\n");
00393 #endif
00394 }
00395 
00396 void WIZnet_Chip::spi_read(uint16_t addr, uint8_t cb, uint8_t *buf, uint16_t len)
00397 {
00398     cs = 0;
00399     spi->write(addr >> 8);
00400     spi->write(addr & 0xff);
00401     spi->write(cb);
00402     for(int i = 0; i < len; i++) {
00403         buf[i] = spi->write(0);
00404     }
00405     cs = 1;
00406 
00407 #if DBG_SPI
00408     debug("[SPI]R %04x(%02x %d)", addr, cb, len);
00409     for(int i = 0; i < len; i++) {
00410         debug(" %02x", buf[i]);
00411         if (i > 16) {
00412             debug(" ...");
00413             break;
00414         }
00415     }
00416     debug("\r\n");
00417     if ((addr&0xf0ff)==0x4026 || (addr&0xf0ff)==0x4003) {
00418         wait_ms(200);
00419     }
00420 #endif
00421 }
00422 
00423 uint32_t str_to_ip(const char* str)
00424 {
00425     uint32_t ip = 0;
00426     char* p = (char*)str;
00427     for(int i = 0; i < 4; i++) {
00428         ip |= atoi(p);
00429         p = strchr(p, '.');
00430         if (p == NULL) {
00431             break;
00432         }
00433         ip <<= 8;
00434         p++;
00435     }
00436     return ip;
00437 }
00438 
00439 void printfBytes(char* str, uint8_t* buf, int len)
00440 {
00441     printf("%s %d:", str, len);
00442     for(int i = 0; i < len; i++) {
00443         printf(" %02x", buf[i]);
00444     }
00445     printf("\n");
00446 }
00447 
00448 void printHex(uint8_t* buf, int len)
00449 {
00450     for(int i = 0; i < len; i++) {
00451         if ((i%16) == 0) {
00452             printf("%p", buf+i);
00453         }
00454         printf(" %02x", buf[i]);
00455         if ((i%16) == 15) {
00456             printf("\n");
00457         }
00458     }
00459     printf("\n");
00460 }
00461 
00462 void debug_hex(uint8_t* buf, int len)
00463 {
00464     for(int i = 0; i < len; i++) {
00465         if ((i%16) == 0) {
00466             debug("%p", buf+i);
00467         }
00468         debug(" %02x", buf[i]);
00469         if ((i%16) == 15) {
00470             debug("\n");
00471         }
00472     }
00473     debug("\n");
00474 }
00475 
00476 int WIZnet_Chip::ethernet_link(void) {
00477     int val = getPHYCFGR();
00478     return val & 0x01;
00479 }
00480 
00481 int WIZnet_Chip::ethernet_speed(void) {
00482     int val = getPHYCFGR();
00483     return val &0x02 ? 100 : 10;
00484 }
00485 
00486 bool WIZnet_Chip::ethernet_fullduplex(void) {
00487     int val = getPHYCFGR();
00488     return val & 0x04;
00489 }
00490 
00491 
00492 
00493 void WIZnet_Chip::ethernet_set_link(int speed, int duplex) {
00494     uint32_t val=0;
00495     if((speed < 0) || (speed > 1)) {
00496         val = (PHYCFGR_OPMDC_ALLA)<<3; 
00497     } else {
00498         val = (((speed&0x01)<<1)+ (duplex&0x01))<<3; 
00499     }
00500     setPHYCFGR((uint8_t)(PHYCFGR_RST&(PHYCFGR_OPMD|val)));
00501     wait(0.2);
00502     setPHYCFGR((uint8_t)((~PHYCFGR_RST)|(PHYCFGR_OPMD|val)));
00503     wait(0.2);
00504 }
00505 
00506     void WIZnet_Chip::reg_rd_mac(uint16_t addr, uint8_t* data) {
00507         spi_read(addr, 0x00, data, 6);
00508     }
00509 
00510     void WIZnet_Chip::reg_wr_ip(uint16_t addr, uint8_t cb, const char* ip) {
00511         uint8_t buf[4];
00512         char* p = (char*)ip;
00513         for(int i = 0; i < 4; i++) {
00514             buf[i] = atoi(p);
00515             p = strchr(p, '.');
00516             if (p == NULL) {
00517                 break;
00518             }
00519             p++;
00520         }
00521         spi_write(addr, cb, buf, sizeof(buf));
00522     }
00523     
00524     void WIZnet_Chip::sreg_ip(int socket, uint16_t addr, const char* ip) {
00525         reg_wr_ip(addr, (0x0C + (socket << 5)), ip);
00526     }
00527     
00528     void WIZnet_Chip::reg_rd_ip_byte(uint16_t addr, uint8_t* data) {
00529         spi_read(addr, 0x00, data, 4);
00530     }
00531     
00532     void WIZnet_Chip::reg_wr_ip_byte(uint16_t addr, uint8_t* data) {
00533         spi_write(addr, 0x04, data, 4);
00534     }
00535 
00536 
00537 #endif
00538