Update of W5500 Interface for mbed-os

Dependents:   PwrCond_mbed5

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   0 
00038 #define w5500_ACCEPT_TIMEOUT 3000
00039 
00040 /* Interface implementation */
00041 
00042 W5500Interface::W5500Interface(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset) :
00043         WIZnet_Chip(mosi, miso, sclk, cs, reset)
00044 {
00045     ip_set = false;
00046     init();
00047 }
00048 
00049 W5500Interface::W5500Interface(SPI* spi, PinName cs, PinName reset) :
00050         WIZnet_Chip(spi, cs, reset)
00051 {
00052     ip_set = false;
00053     init();
00054 }
00055 
00056 w5500_socket* W5500Interface::get_sock(int fd) 
00057 {
00058     for (int i=0; i<MAX_SOCK_NUM ; i++) {
00059         if (w5500_sockets[i].fd == -1) {
00060             w5500_sockets[i].fd            = fd;
00061             w5500_sockets[i].proto         = NSAPI_TCP;
00062             w5500_sockets[i].connected     = false;
00063             w5500_sockets[i].callback      = NULL;
00064             w5500_sockets[i].callback_data = NULL;
00065             return &w5500_sockets[i];
00066         }
00067     }
00068     return NULL;
00069 }
00070 
00071 void W5500Interface::init_socks() 
00072 {
00073     for (int i=0; i<MAX_SOCK_NUM ; i++) {
00074         w5500_sockets[i].fd            = -1;
00075         w5500_sockets[i].proto         = NSAPI_TCP;
00076         w5500_sockets[i].callback      = NULL;
00077         w5500_sockets[i].callback_data = NULL;
00078         w5500_sockets[i].connected     = false;
00079     }
00080     
00081     //initialize the socket isr
00082     _daemon = new Thread(osPriorityNormal, 1024);
00083     _daemon->start(callback(this, &W5500Interface::daemon));
00084 } 
00085 
00086 int W5500Interface::init()
00087 {
00088     WIZnet_Chip::reg_wr<uint32_t>(SIPR, 0x00000000); // local ip "0.0.0.0"
00089     //WIZnet_Chip::reg_wr<uint8_t>(SIMR, 0xFF); // 
00090     reset();
00091     init_socks();
00092     return 0;
00093 }
00094 
00095 int W5500Interface::init(uint8_t * mac)
00096 {
00097     //
00098     for (int i =0; i < 6; i++) this->mac[i] = mac[i];
00099     //
00100     reset();
00101     setmac();    
00102     init_socks();
00103     return 0;
00104 }
00105 
00106 // add this function, because sometimes no needed MAC address in init calling.
00107 int W5500Interface::init(const char* ip, const char* mask, const char* gateway)
00108 {
00109     this->ip = str_to_ip(ip);
00110     strcpy(ip_string, ip);
00111     ip_set = true;
00112     this->netmask = str_to_ip(mask);
00113     this->gateway = str_to_ip(gateway);
00114     reset();
00115     
00116     // @Jul. 8. 2014 add code. should be called to write chip.
00117     setip(); 
00118     init_socks();
00119     
00120     return 0;
00121 }
00122 
00123 int W5500Interface::init(uint8_t * mac, const char* ip, const char* mask, const char* gateway)
00124 {
00125     //
00126     for (int i =0; i < 6; i++) this->mac[i] = mac[i];
00127     //
00128     this->ip = str_to_ip(ip);
00129     strcpy(ip_string, ip);
00130     ip_set = true;
00131     this->netmask = str_to_ip(mask);
00132     this->gateway = str_to_ip(gateway);
00133     reset();
00134 
00135     // @Jul. 8. 2014 add code. should be called to write chip.
00136     setmac();
00137     setip();
00138     init_socks();
00139     
00140     return 0;
00141 }
00142 
00143 void W5500Interface::daemon () {
00144     for (;;) {
00145         for (int i=0; i<MAX_SOCK_NUM ; i++) {
00146             if (w5500_sockets[i].fd > 0 && w5500_sockets[i].callback) {
00147                 int size = sreg<uint16_t>(w5500_sockets[i].fd, Sn_RX_RSR);
00148                 if (size > 0) {
00149                     led1 = !led1;    
00150                     w5500_sockets[i].callback(w5500_sockets[i].callback_data);
00151                 }
00152             }
00153         }
00154         wait(0.2);
00155     }
00156 }
00157 
00158 int W5500Interface::connect()
00159 {
00160     if (WIZnet_Chip::setip() == false) return NSAPI_ERROR_DHCP_FAILURE;
00161     return 0;
00162 }
00163 
00164 int W5500Interface::disconnect()
00165 {
00166     WIZnet_Chip::disconnect();
00167     return 0;
00168 }
00169 
00170 const char *W5500Interface::get_ip_address()
00171 {
00172     uint32_t ip = reg_rd<uint32_t>(SIPR);
00173     snprintf(ip_string, sizeof(ip_string), "%d.%d.%d.%d", (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff);
00174     return ip_string;
00175 }
00176 
00177 const char *W5500Interface::get_mac_address()
00178 {
00179     uint8_t mac[6];
00180     reg_rd_mac(SHAR, mac);
00181     snprintf(mac_string, sizeof(mac_string), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
00182     return mac_string; 
00183 }
00184 
00185 nsapi_error_t W5500Interface::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
00186 {
00187     //a socket is created the same way regardless of the protocol
00188     int sock_fd = WIZnet_Chip::new_socket();
00189     if (sock_fd < 0) {
00190         return NSAPI_ERROR_NO_SOCKET;
00191     }
00192     
00193     w5500_socket *h = get_sock(sock_fd);
00194     
00195     if (!h) {
00196         return NSAPI_ERROR_NO_SOCKET;
00197     }
00198 
00199     h->proto         = proto;
00200     h->connected     = false;
00201     h->callback      = NULL;
00202     h->callback_data = NULL;
00203    
00204     //new up an int to store the socket fd 
00205     *handle = h;
00206     
00207     return 0;
00208 }
00209 
00210 void W5500Interface::signal_event(nsapi_socket_t handle)
00211 {
00212     if (SKT(handle)->callback != NULL) {
00213         SKT(handle)->callback(SKT(handle)->callback_data);
00214     }
00215 }
00216 
00217 nsapi_error_t W5500Interface::socket_close(nsapi_socket_t handle)
00218 {
00219     if (handle == NULL) return 0;
00220     WIZnet_Chip::close(SKT(handle)->fd);
00221     
00222     SKT(handle)->fd = -1;
00223 
00224     return 0;
00225 }
00226 
00227 nsapi_error_t W5500Interface::socket_bind(nsapi_socket_t handle, const SocketAddress &address)
00228 {
00229     if (handle < 0) {
00230         return NSAPI_ERROR_DEVICE_ERROR;
00231     }
00232 
00233     switch (SKT(handle)->proto) {
00234         case NSAPI_UDP:
00235             // set local port
00236             if (address.get_port() != 0) {
00237                 WIZnet_Chip::sreg<uint16_t>(SKT(handle)->fd, Sn_PORT, address.get_port());
00238             } else {
00239                 udp_local_port++;
00240                 WIZnet_Chip::sreg<uint16_t>(SKT(handle)->fd, Sn_PORT, udp_local_port);
00241             }
00242             // set udp protocol
00243             WIZnet_Chip::setProtocol(SKT(handle)->fd, UDP);
00244             WIZnet_Chip::scmd(SKT(handle)->fd, OPEN);
00245             return 0;
00246         case NSAPI_TCP:
00247             listen_port = address.get_port();
00248             // set TCP protocol
00249             WIZnet_Chip::setProtocol(SKT(handle)->fd, TCP);
00250             // set local port
00251             WIZnet_Chip::sreg<uint16_t>(SKT(handle)->fd, Sn_PORT, address.get_port());
00252             // connect the network
00253             WIZnet_Chip::scmd(SKT(handle)->fd, OPEN);
00254             return 0;
00255     }
00256     
00257     return NSAPI_ERROR_DEVICE_ERROR;
00258 }
00259 
00260 nsapi_error_t W5500Interface::socket_listen(nsapi_socket_t handle, int backlog)
00261 {
00262     if (SKT(handle)->fd < 0) {
00263         return NSAPI_ERROR_NO_SOCKET;
00264     }
00265     if (backlog != 1) {
00266         return NSAPI_ERROR_NO_SOCKET;
00267     }
00268     WIZnet_Chip::scmd(SKT(handle)->fd, LISTEN);
00269     return 0;
00270 }
00271 
00272 nsapi_size_or_error_t W5500Interface::socket_connect(nsapi_socket_t handle, const SocketAddress &address)
00273 {
00274     //check for a valid socket
00275     if (SKT(handle)->fd < 0) {
00276         return NSAPI_ERROR_NO_SOCKET;
00277     }
00278     
00279     //before we attempt to connect, we are not connected
00280     SKT(handle)->connected = false;
00281 
00282     //try to connect
00283     if (!WIZnet_Chip::connect(SKT(handle)->fd, address.get_ip_address(), address.get_port(), 0)) {
00284         return -1;
00285     }
00286 
00287     //we are now connected
00288     SKT(handle)->connected = true;
00289 
00290     return 0;
00291 }
00292 
00293 nsapi_error_t W5500Interface::socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address)
00294 {
00295     if (SKT(server)->fd < 0) {
00296         return NSAPI_ERROR_NO_SOCKET;
00297     }
00298     
00299     SKT(server)->connected = false;
00300 
00301     Timer t;
00302     t.reset();
00303     t.start();
00304 
00305     while(1) {
00306         //if (t.read_ms() > w5500_ACCEPT_TIMEOUT) {
00307         //    printf("W5500Interface::socket_accept, timed out\r\n");
00308         //    return NSAPI_ERROR_WOULD_BLOCK;
00309         //}
00310         
00311         nsapi_error_t err = WIZnet_Chip::sreg<uint8_t>(SKT(server)->fd, Sn_SR);
00312         
00313         if (err == SOCK_ESTABLISHED) {
00314             break;
00315         }
00316     }
00317     
00318     //get socket for the connection
00319     *handle = get_sock(SKT(server)->fd);
00320     
00321     if (!(*handle)) {
00322         error("No more socketa for binding");
00323         return NSAPI_ERROR_NO_SOCKET;
00324     }
00325    
00326     //give it all of the socket info from the server
00327     SKT(*handle)->proto     = SKT(server)->proto;
00328     SKT(*handle)->connected = true;
00329 
00330     //create a new tcp socket for the server
00331     SKT(server)->fd = WIZnet_Chip::new_socket();
00332     if (SKT(server)->fd < 0) {
00333         error("Unable to open a new socket");
00334         return NSAPI_ERROR_NO_SOCKET;
00335     }
00336     
00337     SKT(server)->proto     = NSAPI_TCP;
00338     SKT(server)->connected = false;
00339    
00340     SocketAddress _addr;
00341     _addr.set_port(listen_port);
00342     
00343     // and then, for the next connection, server socket should be assigned new one.
00344     if (socket_bind(server, _addr) < 0) {
00345         error("No more socketa for binding");
00346         return NSAPI_ERROR_NO_SOCKET;
00347     }
00348     
00349     if (socket_listen(server, 1) < 0) {
00350         error("No more sockets for listening");
00351     }
00352     
00353     if (address) {
00354         uint32_t ip = WIZnet_Chip::sreg<uint32_t>(SKT(*handle)->fd, Sn_DIPR);
00355         char host[17];
00356         snprintf(host, sizeof(host), "%d.%d.%d.%d", (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff);
00357         int port = WIZnet_Chip::sreg<uint16_t>(SKT(*handle)->fd, Sn_DPORT);
00358         
00359         _addr.set_ip_address(host);
00360         _addr.set_port(port);
00361         *address = _addr;
00362     }
00363 
00364     return 0;
00365 }
00366 
00367 nsapi_size_or_error_t W5500Interface::socket_send(nsapi_socket_t handle, const void *data, nsapi_size_t size)
00368 {
00369     int writtenLen = 0;
00370     while (writtenLen < size) {
00371         int _size =  WIZnet_Chip::wait_writeable(SKT(handle)->fd, w5500_WAIT_TIMEOUT);
00372         if (_size < 0) {
00373             return NSAPI_ERROR_WOULD_BLOCK;
00374         }
00375         if (_size > (size-writtenLen)) {
00376             _size = (size-writtenLen);
00377         }
00378         int ret = WIZnet_Chip::send(SKT(handle)->fd, (char*)data, (int)_size);
00379         if (ret < 0) {
00380             return -1;
00381         }
00382         writtenLen += ret;
00383     }
00384     return writtenLen;
00385 }
00386 
00387 nsapi_size_or_error_t W5500Interface::socket_recv(nsapi_socket_t handle, void *data, nsapi_size_t size)
00388 {
00389     // add to cover exception.
00390     if ((SKT(handle)->fd < 0) || !SKT(handle)->connected) {
00391         return -1;
00392     }
00393 
00394     int _size = WIZnet_Chip::wait_readable(SKT(handle)->fd, w5500_WAIT_TIMEOUT);
00395     
00396     if (_size < 0) {
00397         return NSAPI_ERROR_WOULD_BLOCK;
00398     }
00399     
00400     if (_size > size) {
00401         _size = size;
00402     }
00403     return WIZnet_Chip::recv(SKT(handle)->fd, (char*)data, (int)_size);
00404 }
00405 
00406 nsapi_size_or_error_t W5500Interface::socket_sendto(nsapi_socket_t handle, const SocketAddress &address,
00407             const void *data, nsapi_size_t size)
00408 {
00409     int len = WIZnet_Chip::wait_writeable(SKT(handle)->fd, w5500_WAIT_TIMEOUT, size-1);
00410     if (len < 0) {
00411         return NSAPI_ERROR_WOULD_BLOCK;;
00412     }
00413     
00414     // set remote host
00415     WIZnet_Chip::sreg_ip(SKT(handle)->fd, Sn_DIPR, address.get_ip_address());
00416     // set remote port
00417     WIZnet_Chip::sreg<uint16_t>(SKT(handle)->fd, Sn_DPORT, address.get_port());
00418     
00419     return WIZnet_Chip::send(SKT(handle)->fd, (const char*)data, size);
00420 }
00421 
00422 nsapi_size_or_error_t W5500Interface::socket_recvfrom(nsapi_socket_t handle, SocketAddress *address,
00423             void *buffer, nsapi_size_t size)
00424 {
00425     //check for null pointers
00426     if (address == NULL || buffer == NULL) return -1;
00427     
00428     uint8_t info[8];
00429     int len = WIZnet_Chip::wait_readable(SKT(handle)->fd, w5500_WAIT_TIMEOUT, sizeof(info));
00430     if (len < 0) {
00431         return NSAPI_ERROR_WOULD_BLOCK;
00432     }
00433 
00434     //receive endpoint information
00435     WIZnet_Chip::recv(SKT(handle)->fd, (char*)info, sizeof(info));
00436     
00437     char addr[17];
00438     snprintf(addr, sizeof(addr), "%d.%d.%d.%d", info[0], info[1], info[2], info[3]);
00439     uint16_t port = info[4]<<8|info[5];
00440     address->set_ip_address(addr);
00441     address->set_port(port);
00442    
00443     int udp_size = info[6]<<8|info[7];
00444 
00445     if (udp_size > (len-sizeof(info))) {
00446         return -1;
00447     }
00448     
00449     //receive from socket
00450     return WIZnet_Chip::recv(SKT(handle)->fd, (char*)buffer, udp_size);
00451 }
00452 
00453 void W5500Interface::socket_attach(void *handle, void (*callback)(void *), void *data)
00454 {
00455     if (handle == NULL) return;
00456     
00457     SKT(handle)->callback       = callback;
00458     SKT(handle)->callback_data  = data;
00459 }