For mbed OS-5 version for WIZnet Ethernet Interface, this is Library using Hardware TCP/IP chip, W5500 and TCP/IP Offload Engine, W7500.

Dependents:   ledMapperTest

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     // write MAC address inside the WZTOE MAC address register
00171     reg_wr_mac(SHAR, mac);
00172 #endif
00173     // set RX and TX buffer size
00174 #if 0
00175     for (int socket = 0; socket < MAX_SOCK_NUM; socket++) {
00176         sreg<uint8_t>(socket, Sn_RXBUF_SIZE, 2);
00177         sreg<uint8_t>(socket, Sn_TXBUF_SIZE, 2);
00178     }
00179 #endif
00180 }
00181 
00182 
00183 bool WIZnet_Chip::close(int socket)
00184 {
00185     if (socket < 0) {
00186         return false;
00187     }
00188     // if not connected, return
00189     if (sreg<uint8_t>(socket, Sn_SR) == SOCK_CLOSED) {
00190         return true;
00191     }
00192     if (sreg<uint8_t>(socket, Sn_MR) == TCP) {
00193         scmd(socket, DISCON);
00194     }
00195     scmd(socket, CLOSE);
00196     sreg<uint8_t>(socket, Sn_IR, 0xff);
00197     return true;
00198 }
00199 
00200 int WIZnet_Chip::wait_readable(int socket, int wait_time_ms, int req_size)
00201 {
00202     if (socket < 0) {
00203         return -1;
00204     }
00205     Timer t;
00206     t.reset();
00207     t.start();
00208     while(1) {
00209         //int size = sreg<uint16_t>(socket, Sn_RX_RSR);
00210         // during the reading Sn_RX_RXR, it has the possible change of this register.
00211         // so read twice and get same value then use size information.
00212         int size, size2;
00213         do {
00214             size = sreg<uint16_t>(socket, Sn_RX_RSR);
00215             size2 = sreg<uint16_t>(socket, Sn_RX_RSR);
00216         } while (size != size2);
00217         
00218         if (size > req_size) {
00219             return size;
00220         }
00221         if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
00222             break;
00223         }
00224     }
00225     return -1;
00226 }
00227 
00228 int WIZnet_Chip::wait_writeable(int socket, int wait_time_ms, int req_size)
00229 {
00230     if (socket < 0) {
00231         return -1;
00232     }
00233     Timer t;
00234     t.reset();
00235     t.start();
00236     while(1) {
00237         //int size = sreg<uint16_t>(socket, Sn_TX_FSR);
00238         // during the reading Sn_TX_FSR, it has the possible change of this register.
00239         // so read twice and get same value then use size information.
00240         int size, size2;
00241         do {
00242             size = sreg<uint16_t>(socket, Sn_TX_FSR);
00243             size2 = sreg<uint16_t>(socket, Sn_TX_FSR);
00244         } while (size != size2);
00245         
00246         if (size > req_size) {
00247             return size;
00248         }
00249         if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
00250             break;
00251         }
00252     }
00253     return -1;
00254 }
00255 
00256 int WIZnet_Chip::send(int socket, const char * str, int len)
00257 {
00258     if (socket < 0) {
00259         return -1;
00260     }
00261     uint16_t ptr = sreg<uint16_t>(socket, Sn_TX_WR);
00262     uint8_t cntl_byte = (0x14 + (socket << 5));
00263     spi_write(ptr, cntl_byte, (uint8_t*)str, len);
00264     sreg<uint16_t>(socket, Sn_TX_WR, ptr + len);
00265     scmd(socket, SEND);
00266     uint8_t tmp_Sn_IR;
00267     while (( (tmp_Sn_IR = sreg<uint8_t>(socket, Sn_IR)) & INT_SEND_OK) != INT_SEND_OK) {
00268         // @Jul.10, 2014 fix contant name, and udp sendto function.
00269         switch (sreg<uint8_t>(socket, Sn_SR)) {
00270             case SOCK_CLOSED :
00271                 close(socket);
00272                 return 0;
00273                 //break;
00274             case SOCK_UDP :
00275                 // ARP timeout is possible.
00276                 if ((tmp_Sn_IR & INT_TIMEOUT) == INT_TIMEOUT) {
00277                     sreg<uint8_t>(socket, Sn_IR, INT_TIMEOUT);
00278                     return 0;
00279                 }
00280                 break;
00281             default :
00282                 break;
00283         }
00284     }
00285     /*
00286         while ((sreg<uint8_t>(socket, Sn_IR) & INT_SEND_OK) != INT_SEND_OK) {
00287             if (sreg<uint8_t>(socket, Sn_SR) == CLOSED) {
00288                 close(socket);
00289                 return 0;
00290             }
00291         }
00292     */
00293     sreg<uint8_t>(socket, Sn_IR, INT_SEND_OK);
00294 
00295     return len;
00296 }
00297 
00298 int WIZnet_Chip::recv(int socket, char* buf, int len)
00299 {
00300     if (socket < 0) {
00301         return -1;
00302     }
00303     uint16_t ptr = sreg<uint16_t>(socket, Sn_RX_RD);
00304     uint8_t cntl_byte = (0x18 + (socket << 5));
00305     spi_read(ptr, cntl_byte, (uint8_t*)buf, len);
00306     sreg<uint16_t>(socket, Sn_RX_RD, ptr + len);
00307     scmd(socket, RECV);
00308     return len;
00309 }
00310 
00311 int WIZnet_Chip::new_socket()
00312 {
00313     for(int s = 0; s < MAX_SOCK_NUM; s++) {
00314         if (sreg<uint8_t>(s, Sn_SR) == SOCK_CLOSED) {
00315             return s;
00316         }
00317     }
00318     return -1;
00319 }
00320 
00321 uint16_t WIZnet_Chip::new_port()
00322 {
00323     uint16_t port = rand();
00324     port |= 49152;
00325     return port;
00326 }
00327 
00328 bool WIZnet_Chip::link(int wait_time_ms)
00329 {
00330     Timer t;
00331     t.reset();
00332     t.start();
00333     while(1) {
00334         int is_link = ethernet_link();
00335         
00336         if (is_link) {
00337             return true;
00338         }
00339         if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
00340             break;
00341         }
00342     }
00343     return 0;
00344 }
00345 
00346 void WIZnet_Chip::set_link(PHYMode phymode)
00347 {
00348     int speed = -1;
00349     int duplex = 0;
00350 
00351     switch(phymode) {
00352         case AutoNegotiate : speed = -1; duplex = 0; break;
00353         case HalfDuplex10  : speed = 0;  duplex = 0; break;
00354         case FullDuplex10  : speed = 0;  duplex = 1; break;
00355         case HalfDuplex100 : speed = 1;  duplex = 0; break;
00356         case FullDuplex100 : speed = 1;  duplex = 1; break;
00357     }
00358 
00359     ethernet_set_link(speed, duplex);
00360 }
00361 
00362 void WIZnet_Chip::scmd(int socket, Command cmd)
00363 {
00364     sreg<uint8_t>(socket, Sn_CR, cmd);
00365     while(sreg<uint8_t>(socket, Sn_CR));
00366 }
00367 
00368 void WIZnet_Chip::spi_write(uint16_t addr, uint8_t cb, const uint8_t *buf, uint16_t len)
00369 {
00370     cs = 0;
00371     spi->write(addr >> 8);
00372     spi->write(addr & 0xff);
00373     spi->write(cb);
00374     for(int i = 0; i < len; i++) {
00375         spi->write(buf[i]);
00376     }
00377     cs = 1;
00378 
00379 #if DBG_SPI 
00380     debug("[SPI]W %04x(%02x %d)", addr, cb, len);
00381     for(int i = 0; i < len; i++) {
00382         debug(" %02x", buf[i]);
00383         if (i > 16) {
00384             debug(" ...");
00385             break;
00386         }
00387     }
00388     debug("\r\n");
00389 #endif
00390 }
00391 
00392 void WIZnet_Chip::spi_read(uint16_t addr, uint8_t cb, uint8_t *buf, uint16_t len)
00393 {
00394     cs = 0;
00395     spi->write(addr >> 8);
00396     spi->write(addr & 0xff);
00397     spi->write(cb);
00398     for(int i = 0; i < len; i++) {
00399         buf[i] = spi->write(0);
00400     }
00401     cs = 1;
00402 
00403 #if DBG_SPI
00404     debug("[SPI]R %04x(%02x %d)", addr, cb, len);
00405     for(int i = 0; i < len; i++) {
00406         debug(" %02x", buf[i]);
00407         if (i > 16) {
00408             debug(" ...");
00409             break;
00410         }
00411     }
00412     debug("\r\n");
00413     if ((addr&0xf0ff)==0x4026 || (addr&0xf0ff)==0x4003) {
00414         wait_ms(200);
00415     }
00416 #endif
00417 }
00418 
00419 uint32_t str_to_ip(const char* str)
00420 {
00421     uint32_t ip = 0;
00422     char* p = (char*)str;
00423     for(int i = 0; i < 4; i++) {
00424         ip |= atoi(p);
00425         p = strchr(p, '.');
00426         if (p == NULL) {
00427             break;
00428         }
00429         ip <<= 8;
00430         p++;
00431     }
00432     return ip;
00433 }
00434 
00435 void printfBytes(char* str, uint8_t* buf, int len)
00436 {
00437     printf("%s %d:", str, len);
00438     for(int i = 0; i < len; i++) {
00439         printf(" %02x", buf[i]);
00440     }
00441     printf("\n");
00442 }
00443 
00444 void printHex(uint8_t* buf, int len)
00445 {
00446     for(int i = 0; i < len; i++) {
00447         if ((i%16) == 0) {
00448             printf("%p", buf+i);
00449         }
00450         printf(" %02x", buf[i]);
00451         if ((i%16) == 15) {
00452             printf("\n");
00453         }
00454     }
00455     printf("\n");
00456 }
00457 
00458 void debug_hex(uint8_t* buf, int len)
00459 {
00460     for(int i = 0; i < len; i++) {
00461         if ((i%16) == 0) {
00462             debug("%p", buf+i);
00463         }
00464         debug(" %02x", buf[i]);
00465         if ((i%16) == 15) {
00466             debug("\n");
00467         }
00468     }
00469     debug("\n");
00470 }
00471 
00472 int WIZnet_Chip::ethernet_link(void) {
00473     int val = getPHYCFGR();
00474     return (val&0x01);
00475 }
00476 
00477 void WIZnet_Chip::ethernet_set_link(int speed, int duplex) {
00478     uint32_t val=0;
00479     if((speed < 0) || (speed > 1)) {
00480         val = (PHYCFGR_OPMDC_ALLA)<<3; 
00481     } else {
00482         val = (((speed&0x01)<<1)+ (duplex&0x01))<<3; 
00483     }
00484     setPHYCFGR((uint8_t)(PHYCFGR_RST&(PHYCFGR_OPMD|val)));
00485     wait(0.2);
00486     setPHYCFGR((uint8_t)((~PHYCFGR_RST)|(PHYCFGR_OPMD|val)));
00487     wait(0.2);
00488 }
00489 
00490     void WIZnet_Chip::reg_rd_mac(uint16_t addr, uint8_t* data) {
00491         spi_read(addr, 0x00, data, 6);
00492     }
00493 
00494     void WIZnet_Chip::reg_wr_ip(uint16_t addr, uint8_t cb, const char* ip) {
00495         uint8_t buf[4];
00496         char* p = (char*)ip;
00497         for(int i = 0; i < 4; i++) {
00498             buf[i] = atoi(p);
00499             p = strchr(p, '.');
00500             if (p == NULL) {
00501                 break;
00502             }
00503             p++;
00504         }
00505         spi_write(addr, cb, buf, sizeof(buf));
00506     }
00507     
00508     void WIZnet_Chip::sreg_ip(int socket, uint16_t addr, const char* ip) {
00509         reg_wr_ip(addr, (0x0C + (socket << 5)), ip);
00510     }
00511     
00512     void WIZnet_Chip::reg_rd_ip_byte(uint16_t addr, uint8_t* data) {
00513         spi_read(addr, 0x00, data, 4);
00514     }
00515     
00516     void WIZnet_Chip::reg_wr_ip_byte(uint16_t addr, uint8_t* data) {
00517         spi_write(addr, 0x04, data, 4);
00518     }
00519 
00520 
00521 #endif
00522