Update of W5500 Interface for mbed-os

Dependents:   PwrCond_mbed5

Revision:
0:77e050d1fb12
Child:
1:2dee44ea52a9
diff -r 000000000000 -r 77e050d1fb12 W5500Interface.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/W5500Interface.cpp	Fri Jun 02 22:00:49 2017 +0000
@@ -0,0 +1,407 @@
+// EthernetInterface for W5500 2014/8/20
+/*
+// sample usgae. 
+// copy below code block to main code.
+
+#if defined(TARGET_LPC1114)
+    SPI spi(dp2, dp1, dp6); // mosi, miso, sclk
+    EthernetInterface eth(&spi, dp25, dp26); // spi, cs, reset
+    wait(1); // 1 second for stable state
+#elif defined(TARGET_LPC1768)
+    SPI spi(p11, p12, p13); // mosi, miso, sclk
+    EthernetInterface eth(&spi, p14, p15); // spi, cs, reset
+    wait(1); // 1 second for stable state
+#elif defined(TARGET_LPC11U68)
+    SPI spi(P0_9, P0_8, P1_29); // mosi, miso, sclk
+    EthernetInterface eth(&spi, P0_2, P1_28);//, nRESET(p9); // reset pin is dummy, don't affect any pin of WIZ550io
+    spi.format(8,0); // 8bit, mode 0
+    spi.frequency(7000000); // 7MHz
+    wait(1); // 1 second for stable state
+#endif
+
+    eth.init(); //Use DHCP
+    dbg.printf("init\r\n");
+    eth.connect();
+    dbg.printf("IP address: %s\r\n", eth.getIPAddress());
+
+*/
+
+#include "mbed.h"
+#include "W5500Interface.h"
+
+struct w5500_socket {
+   int   fd;
+   nsapi_protocol_t proto;
+   //bool  blocking;
+   //int   timeout;
+   bool  connected;
+}; 
+
+static int udp_local_port = 0;
+
+#define SKT(h) ((w5500_socket*)h)
+#define w5500_WAIT_TIMEOUT   1000
+#define w5500_ACCEPT_TIMEOUT 3000
+
+/* Interface implementation */
+
+W5500Interface::W5500Interface(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset) :
+        WIZnet_Chip(mosi, miso, sclk, cs, reset)
+{
+    ip_set = false;
+    init();
+}
+
+W5500Interface::W5500Interface(SPI* spi, PinName cs, PinName reset) :
+        WIZnet_Chip(spi, cs, reset)
+{
+    ip_set = false;
+    init();
+}
+
+int W5500Interface::init()
+{
+    WIZnet_Chip::reg_wr<uint32_t>(SIPR, 0x00000000); // local ip "0.0.0.0"
+    reset();
+    return 0;
+}
+
+int W5500Interface::init(uint8_t * mac)
+{
+    //
+    for (int i =0; i < 6; i++) this->mac[i] = mac[i];
+    //
+    reset();
+    setmac();    
+    return 0;
+}
+
+// add this function, because sometimes no needed MAC address in init calling.
+int W5500Interface::init(const char* ip, const char* mask, const char* gateway)
+{
+    this->ip = str_to_ip(ip);
+    strcpy(ip_string, ip);
+    ip_set = true;
+    this->netmask = str_to_ip(mask);
+    this->gateway = str_to_ip(gateway);
+    reset();
+    
+    // @Jul. 8. 2014 add code. should be called to write chip.
+    setip(); 
+    
+    return 0;
+}
+
+int W5500Interface::init(uint8_t * mac, const char* ip, const char* mask, const char* gateway)
+{
+    //
+    for (int i =0; i < 6; i++) this->mac[i] = mac[i];
+    //
+    this->ip = str_to_ip(ip);
+    strcpy(ip_string, ip);
+    ip_set = true;
+    this->netmask = str_to_ip(mask);
+    this->gateway = str_to_ip(gateway);
+    reset();
+
+    // @Jul. 8. 2014 add code. should be called to write chip.
+    setmac();
+    setip();
+    
+    return 0;
+}
+
+int W5500Interface::connect()
+{
+    if (WIZnet_Chip::setip() == false) return NSAPI_ERROR_DHCP_FAILURE;
+    return 0;
+}
+
+int W5500Interface::disconnect()
+{
+    WIZnet_Chip::disconnect();
+    return 0;
+}
+
+const char *W5500Interface::get_ip_address()
+{
+    uint32_t ip = reg_rd<uint32_t>(SIPR);
+    snprintf(ip_string, sizeof(ip_string), "%d.%d.%d.%d", (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff);
+    return ip_string;
+}
+
+const char *W5500Interface::get_mac_address()
+{
+    uint8_t mac[6];
+    reg_rd_mac(SHAR, mac);
+    snprintf(mac_string, sizeof(mac_string), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+    return mac_string; 
+}
+
+nsapi_error_t W5500Interface::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
+{
+    printf("W5500Interface::socket_open h = 0x%08x\r\n", *handle);
+    //a socket is created the same way regardless of the protocol
+    int sock_fd = WIZnet_Chip::new_socket();
+    if (sock_fd < 0) {
+        printf("W5500Interface::socket_open NSAPI_ERROR_NO_SOCKETT\r\n");
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+    
+    w5500_socket *h = new w5500_socket;
+    
+    h->fd        = sock_fd;
+    h->proto     = proto;
+    h->connected = false;
+   
+    //new up an int to store the socket fd 
+    *handle = h;
+    
+    printf("W5500Interface::socket_open h = 0x%08x\r\n", h);
+    
+    return 0;
+}
+
+nsapi_error_t W5500Interface::socket_close(nsapi_socket_t handle)
+{
+    printf("W5500Interface::socket_close 0x%08x\r\n", handle);
+    if (handle == NULL) return 0;
+    WIZnet_Chip::close(SKT(handle)->fd);
+    delete SKT(handle);
+    return 0;
+}
+
+nsapi_error_t W5500Interface::socket_bind(nsapi_socket_t handle, const SocketAddress &address)
+{
+    printf("W5500Interface::socket_bind\r\n");
+    if (handle < 0) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    switch (SKT(handle)->proto) {
+        case NSAPI_UDP:
+            // set local port
+            if (address.get_port() != 0) {
+                WIZnet_Chip::sreg<uint16_t>(SKT(handle)->fd, Sn_PORT, address.get_port());
+            } else {
+                udp_local_port++;
+                WIZnet_Chip::sreg<uint16_t>(SKT(handle)->fd, Sn_PORT, udp_local_port);
+            }
+            // set udp protocol
+            WIZnet_Chip::setProtocol(SKT(handle)->fd, UDP);
+            WIZnet_Chip::scmd(SKT(handle)->fd, OPEN);
+            return 0;
+        case NSAPI_TCP:
+            listen_port = address.get_port();
+            // set TCP protocol
+            WIZnet_Chip::setProtocol(SKT(handle)->fd, TCP);
+            // set local port
+            WIZnet_Chip::sreg<uint16_t>(SKT(handle)->fd, Sn_PORT, address.get_port());
+            // connect the network
+            WIZnet_Chip::scmd(SKT(handle)->fd, OPEN);
+            return 0;
+    }
+    
+    return NSAPI_ERROR_DEVICE_ERROR;
+}
+
+nsapi_error_t W5500Interface::socket_listen(nsapi_socket_t handle, int backlog)
+{
+    if (SKT(handle)->fd < 0) {
+        printf("W5500Interface::socket_listen, error no socket 1\r\n");
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+    if (backlog != 1) {
+        printf("W5500Interface::socket_listen, error no socket 2 \r\n");
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+    printf("W5500Interface::socket_listen, listening\r\n");
+    WIZnet_Chip::scmd(SKT(handle)->fd, LISTEN);
+    return 0;
+}
+
+nsapi_size_or_error_t W5500Interface::socket_connect(nsapi_socket_t handle, const SocketAddress &address)
+{
+    //check for a valid socket
+    if (SKT(handle)->fd < 0) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+    
+    //before we attempt to connect, we are not connected
+    SKT(handle)->connected = false;
+
+    //try to connect
+    if (!WIZnet_Chip::connect(SKT(handle)->fd, address.get_ip_address(), address.get_port(), 0)) {
+        return -1;
+    }
+
+    //we are now connected
+    SKT(handle)->connected = true;
+
+    return 0;
+}
+
+nsapi_error_t W5500Interface::socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address)
+{
+    if (SKT(server)->fd < 0) {
+        printf("W5500Interface::socket_accept, error no socket\r\n");
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+    
+    SKT(server)->connected = false;
+
+    Timer t;
+    t.reset();
+    t.start();
+    while(1) {
+        if (t.read_ms() > w5500_ACCEPT_TIMEOUT) {
+            printf("W5500Interface::socket_accept, timed out\r\n");
+            return NSAPI_ERROR_WOULD_BLOCK;
+        }
+        if (WIZnet_Chip::sreg<uint8_t>(SKT(server)->fd, Sn_SR) == SOCK_ESTABLISHED) {
+            printf("W5500Interface::socket_accept, established connection\r\n");
+            break;
+        }
+    }
+    
+    //create a new socket for the connection
+    *handle = new w5500_socket;
+
+    //give it all of the socket info from the server
+    SKT(*handle)->fd        = SKT(server)->fd;
+    SKT(*handle)->proto     = SKT(server)->proto;
+    SKT(*handle)->connected = true;
+    
+    //create a new tcp socket for the server
+    SKT(server)->fd = WIZnet_Chip::new_socket();
+    if (SKT(server)->fd < 0) {
+        error("Unable to open a new socket");
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+    
+    SKT(server)->proto     = NSAPI_TCP;
+    SKT(server)->connected = false;
+   
+    SocketAddress _addr;
+    _addr.set_port(listen_port);
+    
+    printf("opened socket, binding and listening on port %d\r\n", listen_port);
+    
+    // and then, for the next connection, server socket should be assigned new one.
+    if (socket_bind(server, _addr) < 0) {
+        error("No more socketa for binding");
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+    
+    if (socket_listen(server, 1) < 0) {
+        error("No more socket for listening");
+    }
+    
+    if (address) {
+        uint32_t ip = WIZnet_Chip::sreg<uint32_t>(SKT(*handle)->fd, Sn_DIPR);
+        char host[17];
+        snprintf(host, sizeof(host), "%d.%d.%d.%d", (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff);
+        int port = WIZnet_Chip::sreg<uint16_t>(SKT(*handle)->fd, Sn_DPORT);
+        
+        _addr.set_ip_address(host);
+        _addr.set_port(port);
+        *address = _addr;
+    }
+
+    return 0;
+}
+
+nsapi_size_or_error_t W5500Interface::socket_send(nsapi_socket_t handle, const void *data, nsapi_size_t size)
+{
+    printf("W5500Interface::socket_send\r\n");
+
+    int writtenLen = 0;
+    while (writtenLen < size) {
+        int _size =  WIZnet_Chip::wait_writeable(SKT(handle)->fd, w5500_WAIT_TIMEOUT);
+        if (_size < 0) {
+            return NSAPI_ERROR_WOULD_BLOCK;
+        }
+        if (_size > (size-writtenLen)) {
+            _size = (size-writtenLen);
+        }
+        int ret = WIZnet_Chip::send(SKT(handle)->fd, (char*)data, (int)_size);
+        if (ret < 0) {
+            return -1;
+        }
+        writtenLen += ret;
+    }
+    return writtenLen;
+}
+
+nsapi_size_or_error_t W5500Interface::socket_recv(nsapi_socket_t handle, void *data, nsapi_size_t size)
+{
+    // add to cover exception.
+    if ((SKT(handle)->fd < 0) || !SKT(handle)->connected) {
+        return -1;
+    }
+
+    printf("WIZnet_Chip::wait_readable fd = 0x%08x, timeout = %d\r\n", SKT(handle)->fd, w5500_WAIT_TIMEOUT);
+    int _size = WIZnet_Chip::wait_readable(SKT(handle)->fd, w5500_WAIT_TIMEOUT);
+    printf("WIZnet_Chip::wait_readable n = %d\r\n", _size);
+    
+    if (_size < 0) {
+        return NSAPI_ERROR_WOULD_BLOCK;
+    }
+    
+    if (_size > size) {
+        _size = size;
+    }
+    return WIZnet_Chip::recv(SKT(handle)->fd, (char*)data, (int)_size);
+}
+
+nsapi_size_or_error_t W5500Interface::socket_sendto(nsapi_socket_t handle, const SocketAddress &address,
+            const void *data, nsapi_size_t size)
+{
+    int len = WIZnet_Chip::wait_writeable(SKT(handle)->fd, w5500_WAIT_TIMEOUT, size-1);
+    if (len < 0) {
+        return NSAPI_ERROR_WOULD_BLOCK;;
+    }
+    
+    // set remote host
+    WIZnet_Chip::sreg_ip(SKT(handle)->fd, Sn_DIPR, address.get_ip_address());
+    // set remote port
+    WIZnet_Chip::sreg<uint16_t>(SKT(handle)->fd, Sn_DPORT, address.get_port());
+    
+    return WIZnet_Chip::send(SKT(handle)->fd, (const char*)data, size);
+}
+
+nsapi_size_or_error_t W5500Interface::socket_recvfrom(nsapi_socket_t handle, SocketAddress *address,
+            void *buffer, nsapi_size_t size)
+{
+    //check for null pointers
+    if (address == NULL || buffer == NULL) return -1;
+    
+    uint8_t info[8];
+    int len = WIZnet_Chip::wait_readable(SKT(handle)->fd, w5500_WAIT_TIMEOUT, sizeof(info));
+    if (len < 0) {
+        return NSAPI_ERROR_WOULD_BLOCK;
+    }
+
+    //receive endpoint information
+    WIZnet_Chip::recv(SKT(handle)->fd, (char*)info, sizeof(info));
+    
+    char addr[17];
+    snprintf(addr, sizeof(addr), "%d.%d.%d.%d", info[0], info[1], info[2], info[3]);
+    uint16_t port = info[4]<<8|info[5];
+    address->set_ip_address(addr);
+    address->set_port(port);
+   
+    int udp_size = info[6]<<8|info[7];
+
+    if (udp_size > (len-sizeof(info))) {
+        return -1;
+    }
+    
+    //receive from socket
+    return WIZnet_Chip::recv(SKT(handle)->fd, (char*)buffer, udp_size);
+}
+
+void W5500Interface::socket_attach(void *handle, void (*callback)(void *), void *data)
+{
+    printf("W5500Interface::socket_attach\r\n");
+}
\ No newline at end of file