Sergei G / WIZnetInterface

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     sock_any_port = SOCK_ANY_PORT_NUM;
00058 }
00059 
00060 WIZnet_Chip::WIZnet_Chip(SPI* spi, PinName _cs, PinName _reset):
00061     cs(_cs), reset_pin(_reset)
00062 {
00063     this->spi = spi;
00064     cs = 1;
00065     reset_pin = 1;
00066     inst = this;
00067     sock_any_port = SOCK_ANY_PORT_NUM;
00068 }
00069 
00070 bool WIZnet_Chip::setmac()
00071 {
00072 
00073     for (int i =0; i < 6; i++) reg_wr<uint8_t>(SHAR+i, mac[i]);
00074 
00075     return true;
00076 }
00077 
00078 // Set the IP
00079 bool WIZnet_Chip::setip()
00080 {
00081     reg_wr<uint32_t>(SIPR, ip);
00082     reg_wr<uint32_t>(GAR, gateway);
00083     reg_wr<uint32_t>(SUBR, netmask);
00084     return true;
00085 }
00086 
00087 bool WIZnet_Chip::setProtocol(int socket, Protocol p)
00088 {
00089     if (socket < 0) {
00090         return false;
00091     }
00092     sreg<uint8_t>(socket, Sn_MR, p);
00093     return true;
00094 }
00095 
00096 bool WIZnet_Chip::connect(int socket, const char * host, int port, int timeout_ms)
00097 {
00098     if (socket < 0) {
00099         return false;
00100     }
00101     sreg<uint8_t>(socket, Sn_MR, TCP);
00102     scmd(socket, OPEN);
00103     sreg_ip(socket, Sn_DIPR, host);
00104     sreg<uint16_t>(socket, Sn_DPORT, port);
00105     sreg<uint16_t>(socket, Sn_PORT, new_port());
00106     scmd(socket, CONNECT);
00107     Timer t;
00108     t.reset();
00109     t.start();
00110     while(!is_connected(socket)) {
00111         if (t.read_ms() > timeout_ms) {
00112             return false;
00113         }
00114     }
00115     return true;
00116 }
00117 
00118 bool WIZnet_Chip::gethostbyname(const char* host, uint32_t* ip)
00119 {
00120     uint32_t addr = str_to_ip(host);
00121     char buf[17];
00122     snprintf(buf, sizeof(buf), "%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8)&0xff, addr&0xff);
00123     if (strcmp(buf, host) == 0) {
00124         *ip = addr;
00125         return true;
00126     }
00127     DNSClient client;
00128     if(client.lookup(host)) {
00129         *ip = client.ip;
00130         return true;
00131     }
00132     return false;
00133 }
00134 
00135 bool WIZnet_Chip::disconnect()
00136 {
00137     return true;
00138 }
00139 
00140 bool WIZnet_Chip::is_connected(int socket)
00141 {
00142     /*
00143         if (sreg<uint8_t>(socket, Sn_SR) == SOCK_ESTABLISHED) {
00144             return true;
00145         }
00146     */
00147     uint8_t tmpSn_SR;
00148     tmpSn_SR = sreg<uint8_t>(socket, Sn_SR);
00149     // packet sending is possible, when state is SOCK_CLOSE_WAIT.
00150     if ((tmpSn_SR == SOCK_ESTABLISHED) || (tmpSn_SR == SOCK_CLOSE_WAIT)) {
00151         return true;
00152     }
00153     return false;
00154 }
00155 
00156 // Reset the chip & set the buffer
00157 void WIZnet_Chip::reset()
00158 {
00159 #if defined(USE_WIZ550IO_MAC)
00160     //read the MAC address inside the module    
00161     reg_rd_mac(SHAR, mac); 
00162 #endif
00163     // hw reset
00164     reset_pin = 1;
00165     reset_pin = 0;
00166     wait_us(500); // 500us (w5500)
00167     reset_pin = 1;
00168     wait_ms(400); // 400ms (w5500)
00169 #if defined(USE_WIZ550IO_MAC)
00170 #endif
00171 
00172     // set RX and TX buffer size
00173 #if 0
00174     for (int socket = 0; socket < MAX_SOCK_NUM; socket++) {
00175         sreg<uint8_t>(socket, Sn_RXBUF_SIZE, 2);
00176         sreg<uint8_t>(socket, Sn_TXBUF_SIZE, 2);
00177     }
00178 #endif
00179 
00180     // write MAC address inside the WZTOE MAC address register
00181     reg_wr_mac(SHAR, mac);
00182 
00183 }
00184 
00185 
00186 bool WIZnet_Chip::close(int socket)
00187 {
00188     if (socket < 0) {
00189         return false;
00190     }
00191     // if not connected, return
00192     if (sreg<uint8_t>(socket, Sn_SR) == SOCK_CLOSED) {
00193         return true;
00194     }
00195     if (sreg<uint8_t>(socket, Sn_MR) == TCP) {
00196         scmd(socket, DISCON);
00197     }
00198     scmd(socket, CLOSE);
00199     sreg<uint8_t>(socket, Sn_IR, 0xff);
00200     return true;
00201 }
00202 
00203 int WIZnet_Chip::wait_readable(int socket, int wait_time_ms, int req_size)
00204 {
00205     if (socket < 0) {
00206         return -1;
00207     }
00208     Timer t;
00209     t.reset();
00210     t.start();
00211     while(1) {
00212         //int size = sreg<uint16_t>(socket, Sn_RX_RSR);
00213         // during the reading Sn_RX_RXR, it has the possible change of this register.
00214         // so read twice and get same value then use size information.
00215         int size, size2;
00216         do {
00217             size = sreg<uint16_t>(socket, Sn_RX_RSR);
00218             size2 = sreg<uint16_t>(socket, Sn_RX_RSR);
00219         } while (size != size2);
00220         
00221         if (size > req_size) {
00222             return size;
00223         }
00224         if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
00225             break;
00226         }
00227     }
00228     return -1;
00229 }
00230 
00231 int WIZnet_Chip::wait_writeable(int socket, int wait_time_ms, int req_size)
00232 {
00233     if (socket < 0) {
00234         return -1;
00235     }
00236     Timer t;
00237     t.reset();
00238     t.start();
00239     while(1) {
00240         //int size = sreg<uint16_t>(socket, Sn_TX_FSR);
00241         // during the reading Sn_TX_FSR, it has the possible change of this register.
00242         // so read twice and get same value then use size information.
00243         int size, size2;
00244         do {
00245             size = sreg<uint16_t>(socket, Sn_TX_FSR);
00246             size2 = sreg<uint16_t>(socket, Sn_TX_FSR);
00247         } while (size != size2);
00248         
00249         if (size > req_size) {
00250             return size;
00251         }
00252         if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
00253             break;
00254         }
00255     }
00256     return -1;
00257 }
00258 
00259 int WIZnet_Chip::send(int socket, const char * str, int len)
00260 {
00261     if (socket < 0) {
00262         return -1;
00263     }
00264     uint16_t ptr = sreg<uint16_t>(socket, Sn_TX_WR);
00265     uint8_t cntl_byte = (0x14 + (socket << 5));
00266     spi_write(ptr, cntl_byte, (uint8_t*)str, len);
00267     sreg<uint16_t>(socket, Sn_TX_WR, ptr + len);
00268     scmd(socket, SEND);
00269     uint8_t tmp_Sn_IR;
00270     while (( (tmp_Sn_IR = sreg<uint8_t>(socket, Sn_IR)) & INT_SEND_OK) != INT_SEND_OK) {
00271         // @Jul.10, 2014 fix contant name, and udp sendto function.
00272         switch (sreg<uint8_t>(socket, Sn_SR)) {
00273             case SOCK_CLOSED :
00274                 close(socket);
00275                 return 0;
00276                 //break;
00277             case SOCK_UDP :
00278                 // ARP timeout is possible.
00279                 if ((tmp_Sn_IR & INT_TIMEOUT) == INT_TIMEOUT) {
00280                     sreg<uint8_t>(socket, Sn_IR, INT_TIMEOUT);
00281                     return 0;
00282                 }
00283                 break;
00284             default :
00285                 break;
00286         }
00287     }
00288     /*
00289         while ((sreg<uint8_t>(socket, Sn_IR) & INT_SEND_OK) != INT_SEND_OK) {
00290             if (sreg<uint8_t>(socket, Sn_SR) == CLOSED) {
00291                 close(socket);
00292                 return 0;
00293             }
00294         }
00295     */
00296     sreg<uint8_t>(socket, Sn_IR, INT_SEND_OK);
00297 
00298     return len;
00299 }
00300 
00301 int WIZnet_Chip::recv(int socket, char* buf, int len)
00302 {
00303     if (socket < 0) {
00304         return -1;
00305     }
00306     uint16_t ptr = sreg<uint16_t>(socket, Sn_RX_RD);
00307     uint8_t cntl_byte = (0x18 + (socket << 5));
00308     spi_read(ptr, cntl_byte, (uint8_t*)buf, len);
00309     sreg<uint16_t>(socket, Sn_RX_RD, ptr + len);
00310     scmd(socket, RECV);
00311     return len;
00312 }
00313 
00314 int WIZnet_Chip::new_socket()
00315 {
00316     for(int s = 0; s < MAX_SOCK_NUM; s++) {
00317         if (sreg<uint8_t>(s, Sn_SR) == SOCK_CLOSED) {
00318             return s;
00319         }
00320     }
00321     return -1;
00322 }
00323 
00324 uint16_t WIZnet_Chip::new_port()
00325 {
00326     uint16_t port = rand();
00327     port |= 49152;
00328     return port;
00329 }
00330 
00331 bool WIZnet_Chip::link(int wait_time_ms)
00332 {
00333     Timer t;
00334     t.reset();
00335     t.start();
00336     while(1) {
00337         int is_link = ethernet_link();
00338         
00339         if (is_link) {
00340             return true;
00341         }
00342         if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
00343             break;
00344         }
00345     }
00346     return 0;
00347 }
00348 
00349 void WIZnet_Chip::set_link(PHYMode phymode)
00350 {
00351     int speed = -1;
00352     int duplex = 0;
00353 
00354     switch(phymode) {
00355         case AutoNegotiate : speed = -1; duplex = 0; break;
00356         case HalfDuplex10  : speed = 0;  duplex = 0; break;
00357         case FullDuplex10  : speed = 0;  duplex = 1; break;
00358         case HalfDuplex100 : speed = 1;  duplex = 0; break;
00359         case FullDuplex100 : speed = 1;  duplex = 1; break;
00360     }
00361 
00362     ethernet_set_link(speed, duplex);
00363 }
00364 
00365 void WIZnet_Chip::scmd(int socket, Command cmd)
00366 {
00367     sreg<uint8_t>(socket, Sn_CR, cmd);
00368     while(sreg<uint8_t>(socket, Sn_CR));
00369 }
00370 
00371 void WIZnet_Chip::spi_write(uint16_t addr, uint8_t cb, const uint8_t *buf, uint16_t len)
00372 {
00373     cs = 0;
00374     spi->write(addr >> 8);
00375     spi->write(addr & 0xff);
00376     spi->write(cb);
00377     for(int i = 0; i < len; i++) {
00378         spi->write(buf[i]);
00379     }
00380     cs = 1;
00381 
00382 #if DBG_SPI 
00383     debug("[SPI]W %04x(%02x %d)", addr, cb, len);
00384     for(int i = 0; i < len; i++) {
00385         debug(" %02x", buf[i]);
00386         if (i > 16) {
00387             debug(" ...");
00388             break;
00389         }
00390     }
00391     debug("\r\n");
00392 #endif
00393 }
00394 
00395 void WIZnet_Chip::spi_read(uint16_t addr, uint8_t cb, uint8_t *buf, uint16_t len)
00396 {
00397     cs = 0;
00398     spi->write(addr >> 8);
00399     spi->write(addr & 0xff);
00400     spi->write(cb);
00401     for(int i = 0; i < len; i++) {
00402         buf[i] = spi->write(0);
00403     }
00404     cs = 1;
00405 
00406 #if DBG_SPI
00407     debug("[SPI]R %04x(%02x %d)", addr, cb, len);
00408     for(int i = 0; i < len; i++) {
00409         debug(" %02x", buf[i]);
00410         if (i > 16) {
00411             debug(" ...");
00412             break;
00413         }
00414     }
00415     debug("\r\n");
00416     if ((addr&0xf0ff)==0x4026 || (addr&0xf0ff)==0x4003) {
00417         wait_ms(200);
00418     }
00419 #endif
00420 }
00421 
00422 uint32_t str_to_ip(const char* str)
00423 {
00424     uint32_t ip = 0;
00425     char* p = (char*)str;
00426     for(int i = 0; i < 4; i++) {
00427         ip |= atoi(p);
00428         p = strchr(p, '.');
00429         if (p == NULL) {
00430             break;
00431         }
00432         ip <<= 8;
00433         p++;
00434     }
00435     return ip;
00436 }
00437 
00438 void printfBytes(char* str, uint8_t* buf, int len)
00439 {
00440     printf("%s %d:", str, len);
00441     for(int i = 0; i < len; i++) {
00442         printf(" %02x", buf[i]);
00443     }
00444     printf("\n");
00445 }
00446 
00447 void printHex(uint8_t* buf, int len)
00448 {
00449     for(int i = 0; i < len; i++) {
00450         if ((i%16) == 0) {
00451             printf("%p", buf+i);
00452         }
00453         printf(" %02x", buf[i]);
00454         if ((i%16) == 15) {
00455             printf("\n");
00456         }
00457     }
00458     printf("\n");
00459 }
00460 
00461 void debug_hex(uint8_t* buf, int len)
00462 {
00463     for(int i = 0; i < len; i++) {
00464         if ((i%16) == 0) {
00465             debug("%p", buf+i);
00466         }
00467         debug(" %02x", buf[i]);
00468         if ((i%16) == 15) {
00469             debug("\n");
00470         }
00471     }
00472     debug("\n");
00473 }
00474 
00475 int WIZnet_Chip::ethernet_link(void) {
00476     int val = getPHYCFGR();
00477     return (val&0x01);
00478 }
00479 
00480 void WIZnet_Chip::ethernet_set_link(int speed, int duplex) {
00481     uint32_t val=0;
00482     if((speed < 0) || (speed > 1)) {
00483         val = (PHYCFGR_OPMDC_ALLA)<<3; 
00484     } else {
00485         val = (((speed&0x01)<<1)+ (duplex&0x01))<<3; 
00486     }
00487     setPHYCFGR((uint8_t)(PHYCFGR_RST&(PHYCFGR_OPMD|val)));
00488     wait(0.2);
00489     setPHYCFGR((uint8_t)((~PHYCFGR_RST)|(PHYCFGR_OPMD|val)));
00490     wait(0.2);
00491 }
00492 
00493     void WIZnet_Chip::reg_rd_mac(uint16_t addr, uint8_t* data) {
00494         spi_read(addr, 0x00, data, 6);
00495     }
00496 
00497     void WIZnet_Chip::reg_wr_ip(uint16_t addr, uint8_t cb, const char* ip) {
00498         uint8_t buf[4];
00499         char* p = (char*)ip;
00500         for(int i = 0; i < 4; i++) {
00501             buf[i] = atoi(p);
00502             p = strchr(p, '.');
00503             if (p == NULL) {
00504                 break;
00505             }
00506             p++;
00507         }
00508         spi_write(addr, cb, buf, sizeof(buf));
00509     }
00510     
00511     void WIZnet_Chip::sreg_ip(int socket, uint16_t addr, const char* ip) {
00512         reg_wr_ip(addr, (0x0C + (socket << 5)), ip);
00513     }
00514     
00515     void WIZnet_Chip::reg_rd_ip_byte(uint16_t addr, uint8_t* data) {
00516         spi_read(addr, 0x00, data, 4);
00517     }
00518     
00519     void WIZnet_Chip::reg_wr_ip_byte(uint16_t addr, uint8_t* data) {
00520         spi_write(addr, 0x04, data, 4);
00521     }
00522 
00523 
00524 #endif
00525