Update of W5500 Interface for mbed-os
Diff: W5500Interface.cpp
- 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