fork WIZnetInterface

Dependents:   Weather_Forecast_Helloworld_WIZwiki-W750 Weather_Forecast_Helloworld_WIZwiki-W750 Weather_Forecast_Helloworld_WIZwiki-W750_test DHCPAddressAssignment ... more

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