W5500 from SeeedStudio on NUCLEO-L476RG

Dependents:   coap-example Borsch coap-example

Fork of W5500Interface by AMETEK Powervar

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers W5500Interface.cpp Source File

W5500Interface.cpp

00001 // EthernetInterface for W5500 2014/8/20
00002 /*
00003 // sample usgae. 
00004 // copy below code block to main code.
00005 
00006 #if defined(TARGET_LPC1114)
00007     SPI spi(dp2, dp1, dp6); // mosi, miso, sclk
00008     EthernetInterface eth(&spi, dp25, dp26); // spi, cs, reset
00009     wait(1); // 1 second for stable state
00010 #elif defined(TARGET_LPC1768)
00011     SPI spi(p11, p12, p13); // mosi, miso, sclk
00012     EthernetInterface eth(&spi, p14, p15); // spi, cs, reset
00013     wait(1); // 1 second for stable state
00014 #elif defined(TARGET_LPC11U68)
00015     SPI spi(P0_9, P0_8, P1_29); // mosi, miso, sclk
00016     EthernetInterface eth(&spi, P0_2, P1_28);//, nRESET(p9); // reset pin is dummy, don't affect any pin of WIZ550io
00017     spi.format(8,0); // 8bit, mode 0
00018     spi.frequency(7000000); // 7MHz
00019     wait(1); // 1 second for stable state
00020 #endif
00021 
00022     eth.init(); //Use DHCP
00023     dbg.printf("init\r\n");
00024     eth.connect();
00025     dbg.printf("IP address: %s\r\n", eth.getIPAddress());
00026 
00027 */
00028 
00029 #include "mbed.h"
00030 #include "W5500Interface.h"
00031 
00032 static int udp_local_port = 0;
00033 
00034 DigitalOut led1(LED1);
00035 
00036 #define SKT(h) ((w5500_socket*)h)
00037 #define w5500_WAIT_TIMEOUT   1500
00038 #define w5500_ACCEPT_TIMEOUT 3000
00039 
00040 #define w5500_INTF_DBG 0
00041 
00042 #if w5500_INTF_DBG
00043 #define DBG(...) do{debug("[%s:%d]", __PRETTY_FUNCTION__,__LINE__);debug(__VA_ARGS__);} while(0);
00044 #else
00045 #define DBG(...) while(0);
00046 #endif
00047 
00048 
00049 /* Interface implementation */
00050 
00051 W5500Interface::W5500Interface(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset) :
00052         WIZnet_Chip(mosi, miso, sclk, cs, reset)
00053 {
00054     ip_set = false;
00055 }
00056 
00057 W5500Interface::W5500Interface(SPI* spi, PinName cs, PinName reset) :
00058         WIZnet_Chip(spi, cs, reset)
00059 {
00060     ip_set = false;
00061 }
00062 
00063 w5500_socket* W5500Interface::get_sock(int fd) 
00064 {
00065     for (int i=0; i<MAX_SOCK_NUM ; i++) {
00066         if (w5500_sockets[i].fd == -1) {
00067             w5500_sockets[i].fd            = fd;
00068             w5500_sockets[i].proto         = NSAPI_TCP;
00069             w5500_sockets[i].connected     = false;
00070             w5500_sockets[i].callback      = NULL;
00071             w5500_sockets[i].callback_data = NULL;
00072             return &w5500_sockets[i];
00073         }
00074     }
00075     return NULL;
00076 }
00077 
00078 void W5500Interface::init_socks() 
00079 {
00080     for (int i=0; i<MAX_SOCK_NUM ; i++) {
00081         w5500_sockets[i].fd            = -1;
00082         w5500_sockets[i].proto         = NSAPI_TCP;
00083         w5500_sockets[i].callback      = NULL;
00084         w5500_sockets[i].callback_data = NULL;
00085         w5500_sockets[i].connected     = false;
00086     }
00087     
00088     //initialize the socket isr
00089     _daemon = new Thread(osPriorityNormal, 1024);
00090     _daemon->start(callback(this, &W5500Interface::daemon));
00091 } 
00092 
00093 int W5500Interface::init()
00094 {
00095     WIZnet_Chip::reg_wr<uint32_t>(SIPR, 0x00000000); // local ip "0.0.0.0"
00096     //WIZnet_Chip::reg_wr<uint8_t>(SIMR, 0xFF); // 
00097     reset();
00098     init_socks();
00099     return 0;
00100 }
00101 
00102 int W5500Interface::init(uint8_t * mac)
00103 {
00104     WIZnet_Chip::reg_wr<uint32_t>(SIPR, 0x00000000); // local ip "0.0.0.0"
00105     for (int i =0; i < 6; i++) this->mac[i] = mac[i];
00106     setmac();    
00107     reset();  // sets buffers; does not alter MAC
00108     init_socks();
00109     return 0;
00110 }
00111 
00112 // add this function, because sometimes no needed MAC address in init calling.
00113 int W5500Interface::init(const char* ip, const char* mask, const char* gateway)
00114 {
00115     this->ip = str_to_ip(ip);
00116     strcpy(ip_string, ip);
00117     ip_set = true;
00118     this->netmask = str_to_ip(mask);
00119     this->gateway = str_to_ip(gateway);
00120     reset();
00121     
00122     // @Jul. 8. 2014 add code. should be called to write chip.
00123     setip(); 
00124     init_socks();
00125     
00126     return 0;
00127 }
00128 
00129 int W5500Interface::init(uint8_t * mac, const char* ip, const char* mask, const char* gateway)
00130 {
00131     //
00132     for (int i =0; i < 6; i++) this->mac[i] = mac[i];
00133     //
00134     this->ip = str_to_ip(ip);
00135     strcpy(ip_string, ip);
00136     ip_set = true;
00137     this->netmask = str_to_ip(mask);
00138     this->gateway = str_to_ip(gateway);
00139     reset();
00140 
00141     // @Jul. 8. 2014 add code. should be called to write chip.
00142     setmac();
00143     setip();
00144     init_socks();
00145     
00146     return 0;
00147 }
00148 
00149 void W5500Interface::daemon () {
00150     for (;;) {
00151         for (int i=0; i<MAX_SOCK_NUM ; i++) {
00152             if (w5500_sockets[i].fd > 0 && w5500_sockets[i].callback) {
00153                 int size = sreg<uint16_t>(w5500_sockets[i].fd, Sn_RX_RSR);
00154                 if (size > 0) {
00155                     led1 = !led1;    
00156                     w5500_sockets[i].callback(w5500_sockets[i].callback_data);
00157                 }
00158             }
00159         }
00160         wait(0.2);
00161     }
00162 }
00163 
00164 int W5500Interface::connect()
00165 {
00166     if (WIZnet_Chip::setip() == false) return NSAPI_ERROR_DHCP_FAILURE;
00167     return 0;
00168 }
00169 
00170 int W5500Interface::disconnect()
00171 {
00172     WIZnet_Chip::disconnect();
00173     return 0;
00174 }
00175 
00176 const char *W5500Interface::get_ip_address()
00177 {
00178     uint32_t ip = reg_rd<uint32_t>(SIPR);
00179     snprintf(ip_string, sizeof(ip_string), "%d.%d.%d.%d", (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff);
00180     return ip_string;
00181 }
00182 
00183 const char *W5500Interface::get_mac_address()
00184 {
00185     uint8_t mac[6];
00186     reg_rd_mac(SHAR, mac);
00187     snprintf(mac_string, sizeof(mac_string), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
00188     return mac_string; 
00189 }
00190 
00191 void W5500Interface::get_mac(uint8_t mac[6]) 
00192 {
00193     reg_rd_mac(SHAR, mac);
00194 }
00195 
00196 nsapi_error_t W5500Interface::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
00197 {
00198     //a socket is created the same way regardless of the protocol
00199     int sock_fd = WIZnet_Chip::new_socket();
00200     if (sock_fd < 0) {
00201         return NSAPI_ERROR_NO_SOCKET;
00202     }
00203     
00204     w5500_socket *h = get_sock(sock_fd);
00205     
00206     if (!h) {
00207         return NSAPI_ERROR_NO_SOCKET;
00208     }
00209 
00210     h->proto         = proto;
00211     h->connected     = false;
00212     h->callback      = NULL;
00213     h->callback_data = NULL;
00214    
00215     //new up an int to store the socket fd 
00216     *handle = h;
00217     DBG("fd: %d\n", sock_fd);
00218     return 0;
00219 }
00220 
00221 void W5500Interface::signal_event(nsapi_socket_t handle)
00222 {
00223     DBG("fd: %d\n", SKT(handle)->fd);
00224     if (SKT(handle)->callback != NULL) {
00225         SKT(handle)->callback(SKT(handle)->callback_data);
00226     }
00227 }
00228 
00229 nsapi_error_t W5500Interface::socket_close(nsapi_socket_t handle)
00230 {
00231     if (handle == NULL) return 0;
00232     DBG("fd: %d\n", SKT(handle)->fd);
00233     WIZnet_Chip::close(SKT(handle)->fd);
00234     
00235     SKT(handle)->fd = -1;
00236 
00237     return 0;
00238 }
00239 
00240 nsapi_error_t W5500Interface::socket_bind(nsapi_socket_t handle, const SocketAddress &address)
00241 {
00242     if (handle < 0) {
00243         return NSAPI_ERROR_DEVICE_ERROR;
00244     }
00245     DBG("fd: %d, port: %d\n", SKT(handle)->fd, address.get_port());
00246 
00247     switch (SKT(handle)->proto) {
00248         case NSAPI_UDP:
00249             // set local port
00250             if (address.get_port() != 0) {
00251                 WIZnet_Chip::sreg<uint16_t>(SKT(handle)->fd, Sn_PORT, address.get_port());
00252             } else {
00253                 udp_local_port++;
00254                 WIZnet_Chip::sreg<uint16_t>(SKT(handle)->fd, Sn_PORT, udp_local_port);
00255             }
00256             // set udp protocol
00257             WIZnet_Chip::setProtocol(SKT(handle)->fd, UDP);
00258             WIZnet_Chip::scmd(SKT(handle)->fd, OPEN);
00259             return 0;
00260         case NSAPI_TCP:
00261             listen_port = address.get_port();
00262             // set TCP protocol
00263             WIZnet_Chip::setProtocol(SKT(handle)->fd, TCP);
00264             // set local port
00265             WIZnet_Chip::sreg<uint16_t>(SKT(handle)->fd, Sn_PORT, address.get_port());
00266             // connect the network
00267             WIZnet_Chip::scmd(SKT(handle)->fd, OPEN);
00268             return 0;
00269     }
00270     
00271     return NSAPI_ERROR_DEVICE_ERROR;
00272 }
00273 
00274 nsapi_error_t W5500Interface::socket_listen(nsapi_socket_t handle, int backlog)
00275 {
00276     DBG("fd: %d\n", SKT(handle)->fd);
00277     if (SKT(handle)->fd < 0) {
00278         return NSAPI_ERROR_NO_SOCKET;
00279     }
00280     if (backlog != 1) {
00281         return NSAPI_ERROR_NO_SOCKET;
00282     }
00283     WIZnet_Chip::scmd(SKT(handle)->fd, LISTEN);
00284     return 0;
00285 }
00286 
00287 nsapi_size_or_error_t W5500Interface::socket_connect(nsapi_socket_t handle, const SocketAddress &address)
00288 {
00289     DBG("fd: %d\n", SKT(handle)->fd);
00290     //check for a valid socket
00291     if (SKT(handle)->fd < 0) {
00292         return NSAPI_ERROR_NO_SOCKET;
00293     }
00294     
00295     //before we attempt to connect, we are not connected
00296     SKT(handle)->connected = false;
00297 
00298     //try to connect
00299     if (!WIZnet_Chip::connect(SKT(handle)->fd, address.get_ip_address(), address.get_port(), 0)) {
00300         return -1;
00301     }
00302 
00303     //we are now connected
00304     SKT(handle)->connected = true;
00305 
00306     return 0;
00307 }
00308 
00309 nsapi_error_t W5500Interface::socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address)
00310 {
00311     DBG("fd: %d\n", SKT(handle)->fd);
00312     if (SKT(server)->fd < 0) {
00313         return NSAPI_ERROR_NO_SOCKET;
00314     }
00315     
00316     SKT(server)->connected = false;
00317 
00318     Timer t;
00319     t.reset();
00320     t.start();
00321 
00322     while(1) {
00323         //if (t.read_ms() > w5500_ACCEPT_TIMEOUT) {
00324         //    printf("W5500Interface::socket_accept, timed out\r\n");
00325         //    return NSAPI_ERROR_WOULD_BLOCK;
00326         //}
00327         
00328         nsapi_error_t err = WIZnet_Chip::sreg<uint8_t>(SKT(server)->fd, Sn_SR);
00329         
00330         if (err == SOCK_ESTABLISHED) {
00331             break;
00332         }
00333     }
00334     
00335     //get socket for the connection
00336     *handle = get_sock(SKT(server)->fd);
00337     
00338     if (!(*handle)) {
00339         error("No more sockets for binding");
00340         return NSAPI_ERROR_NO_SOCKET;
00341     }
00342    
00343     //give it all of the socket info from the server
00344     SKT(*handle)->proto     = SKT(server)->proto;
00345     SKT(*handle)->connected = true;
00346 
00347     //create a new tcp socket for the server
00348     SKT(server)->fd = WIZnet_Chip::new_socket();
00349     if (SKT(server)->fd < 0) {
00350         error("Unable to open a new socket");
00351         return NSAPI_ERROR_NO_SOCKET;
00352     }
00353     
00354     SKT(server)->proto     = NSAPI_TCP;
00355     SKT(server)->connected = false;
00356    
00357     SocketAddress _addr;
00358     _addr.set_port(listen_port);
00359     
00360     // and then, for the next connection, server socket should be assigned new one.
00361     if (socket_bind(server, _addr) < 0) {
00362         error("No more sockets for binding");
00363         return NSAPI_ERROR_NO_SOCKET;
00364     }
00365     
00366     if (socket_listen(server, 1) < 0) {
00367         error("No more sockets for listening");
00368     }
00369     
00370     if (address) {
00371         uint32_t ip = WIZnet_Chip::sreg<uint32_t>(SKT(*handle)->fd, Sn_DIPR);
00372         char host[17];
00373         snprintf(host, sizeof(host), "%d.%d.%d.%d", (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff);
00374         int port = WIZnet_Chip::sreg<uint16_t>(SKT(*handle)->fd, Sn_DPORT);
00375         
00376         _addr.set_ip_address(host);
00377         _addr.set_port(port);
00378         *address = _addr;
00379     }
00380 
00381     return 0;
00382 }
00383 
00384 nsapi_size_or_error_t W5500Interface::socket_send(nsapi_socket_t handle, const void *data, nsapi_size_t size)
00385 {
00386     DBG("fd: %d\n", SKT(handle)->fd);
00387     int writtenLen = 0;
00388     while (writtenLen < size) {
00389         int _size =  WIZnet_Chip::wait_writeable(SKT(handle)->fd, w5500_WAIT_TIMEOUT);
00390         if (_size < 0) {
00391             return NSAPI_ERROR_WOULD_BLOCK;
00392         }
00393         if (_size > (size-writtenLen)) {
00394             _size = (size-writtenLen);
00395         }
00396         int ret = WIZnet_Chip::send(SKT(handle)->fd, (char*)data, (int)_size);
00397         if (ret < 0) {
00398             DBG("returning error -1\n");
00399             return -1;
00400         }
00401         writtenLen += ret;
00402     }
00403     return writtenLen;
00404 }
00405 
00406 nsapi_size_or_error_t W5500Interface::socket_recv(nsapi_socket_t handle, void *data, nsapi_size_t size)
00407 {
00408     DBG("fd: %d\n", SKT(handle)->fd);
00409     // add to cover exception.
00410     if ((SKT(handle)->fd < 0) || !SKT(handle)->connected) {
00411         return -1;
00412     }
00413 
00414     int _size = WIZnet_Chip::wait_readable(SKT(handle)->fd, w5500_WAIT_TIMEOUT);
00415     
00416     if (_size < 0) {
00417         return NSAPI_ERROR_WOULD_BLOCK;
00418     }
00419     
00420     if (_size > size) {
00421         _size = size;
00422     }
00423     return WIZnet_Chip::recv(SKT(handle)->fd, (char*)data, (int)_size);
00424 }
00425 
00426 nsapi_size_or_error_t W5500Interface::socket_sendto(nsapi_socket_t handle, const SocketAddress &address,
00427             const void *data, nsapi_size_t size)
00428 {
00429     DBG("fd: %d, ip: %s:%d\n", SKT(handle)->fd, address.get_ip_address(), address.get_port());
00430     if (WIZnet_Chip::is_closed(SKT(handle)->fd)) {
00431         nsapi_error_t err = socket_bind(handle, address);
00432         if (err < 0) {
00433             DBG("failed to bind socket: %d\n", err);
00434             return err;
00435         }
00436     }
00437     //compare with original: int size = eth->wait_writeable(_sock_fd, _blocking ? -1 : _timeout, length-1); 
00438     int len = WIZnet_Chip::wait_writeable(SKT(handle)->fd, w5500_WAIT_TIMEOUT, size-1);
00439     if (len < 0) {
00440         DBG("error: NSAPI_ERROR_WOULD_BLOCK\n");
00441         return NSAPI_ERROR_WOULD_BLOCK;;
00442     }
00443     
00444     // set remote host
00445     WIZnet_Chip::sreg_ip(SKT(handle)->fd, Sn_DIPR, address.get_ip_address());
00446     // set remote port
00447     WIZnet_Chip::sreg<uint16_t>(SKT(handle)->fd, Sn_DPORT, address.get_port());
00448     
00449     nsapi_size_or_error_t err = WIZnet_Chip::send(SKT(handle)->fd, (const char*)data, size);
00450     DBG("rv: %d, size: %d\n", err, size);
00451 #if w5500_INTF_DBG
00452     if (err > 0) {
00453         debug("[socket_sendto] data: ");
00454         for(int i = 0; i < err; i++) {
00455             if ((i%16) == 0) {
00456                 debug("\n");
00457             }
00458             debug(" %02x", ((uint8_t*)data)[i]);
00459         }
00460         if ((err-1%16) != 0) {
00461             debug("\n");
00462         }
00463     }
00464 #endif
00465     return err;
00466 }
00467 
00468 nsapi_size_or_error_t W5500Interface::socket_recvfrom(nsapi_socket_t handle, SocketAddress *address,
00469             void *buffer, nsapi_size_t size)
00470 {
00471     DBG("fd: %d\n", SKT(handle)->fd);
00472     //check for null pointers
00473     if (buffer == NULL) {
00474         DBG("buffer is NULL; receive is ABORTED\n");
00475         return -1;
00476     }
00477    
00478     uint8_t info[8];
00479     int len = WIZnet_Chip::wait_readable(SKT(handle)->fd, w5500_WAIT_TIMEOUT, sizeof(info));
00480     if (len < 0) {
00481         DBG("error: NSAPI_ERROR_WOULD_BLOCK\n");
00482         return NSAPI_ERROR_WOULD_BLOCK;
00483     }
00484 
00485     //receive endpoint information
00486     WIZnet_Chip::recv(SKT(handle)->fd, (char*)info, sizeof(info));
00487     
00488     char addr[17];
00489     snprintf(addr, sizeof(addr), "%d.%d.%d.%d", info[0], info[1], info[2], info[3]);
00490     uint16_t port = info[4]<<8|info[5];
00491     // original behavior was to terminate execution if address is NULL
00492     if (address != NULL) {
00493         //DBG("[socket_recvfrom] warn: addressis NULL");
00494         address->set_ip_address(addr);
00495         address->set_port(port);
00496     }
00497    
00498     int udp_size = info[6]<<8|info[7];
00499 
00500     if (udp_size > (len-sizeof(info))) {
00501         DBG("error: udp_size > (len-sizeof(info))\n");
00502         return -1;
00503     }
00504     
00505     //receive from socket
00506     nsapi_size_or_error_t err = WIZnet_Chip::recv(SKT(handle)->fd, (char*)buffer, udp_size);
00507     DBG("rv: %d\n", err);
00508 #if w5500_INTF_DBG
00509     if (err > 0) {
00510         debug("[socket_recvfrom] buffer:");
00511         for(int i = 0; i < err; i++) {
00512             if ((i%16) == 0) {
00513                 debug("\n");
00514             }
00515             debug(" %02x", ((uint8_t*)buffer)[i]);
00516         }
00517         if ((err-1%16) != 0) {
00518             debug("\n");
00519         }
00520     }
00521 #endif
00522     return  err;
00523 }
00524 
00525 void W5500Interface::socket_attach(void *handle, void (*callback)(void *), void *data)
00526 {
00527     if (handle == NULL) return;
00528     DBG("fd: %d, callback: %p\n", SKT(handle)->fd, callback);
00529     SKT(handle)->callback       = callback;
00530     SKT(handle)->callback_data  = data;
00531 }