Update of W5500 Interface for mbed-os
W5500Interface.cpp
- Committer:
- dgriffin65
- Date:
- 2017-06-15
- Revision:
- 1:2dee44ea52a9
- Parent:
- 0:77e050d1fb12
File content as of revision 1:2dee44ea52a9:
// 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" static int udp_local_port = 0; DigitalOut led1(LED1); #define SKT(h) ((w5500_socket*)h) #define w5500_WAIT_TIMEOUT 0 #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(); } w5500_socket* W5500Interface::get_sock(int fd) { for (int i=0; i<MAX_SOCK_NUM ; i++) { if (w5500_sockets[i].fd == -1) { w5500_sockets[i].fd = fd; w5500_sockets[i].proto = NSAPI_TCP; w5500_sockets[i].connected = false; w5500_sockets[i].callback = NULL; w5500_sockets[i].callback_data = NULL; return &w5500_sockets[i]; } } return NULL; } void W5500Interface::init_socks() { for (int i=0; i<MAX_SOCK_NUM ; i++) { w5500_sockets[i].fd = -1; w5500_sockets[i].proto = NSAPI_TCP; w5500_sockets[i].callback = NULL; w5500_sockets[i].callback_data = NULL; w5500_sockets[i].connected = false; } //initialize the socket isr _daemon = new Thread(osPriorityNormal, 1024); _daemon->start(callback(this, &W5500Interface::daemon)); } int W5500Interface::init() { WIZnet_Chip::reg_wr<uint32_t>(SIPR, 0x00000000); // local ip "0.0.0.0" //WIZnet_Chip::reg_wr<uint8_t>(SIMR, 0xFF); // reset(); init_socks(); return 0; } int W5500Interface::init(uint8_t * mac) { // for (int i =0; i < 6; i++) this->mac[i] = mac[i]; // reset(); setmac(); init_socks(); 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(); init_socks(); 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(); init_socks(); return 0; } void W5500Interface::daemon () { for (;;) { for (int i=0; i<MAX_SOCK_NUM ; i++) { if (w5500_sockets[i].fd > 0 && w5500_sockets[i].callback) { int size = sreg<uint16_t>(w5500_sockets[i].fd, Sn_RX_RSR); if (size > 0) { led1 = !led1; w5500_sockets[i].callback(w5500_sockets[i].callback_data); } } } wait(0.2); } } 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) { //a socket is created the same way regardless of the protocol int sock_fd = WIZnet_Chip::new_socket(); if (sock_fd < 0) { return NSAPI_ERROR_NO_SOCKET; } w5500_socket *h = get_sock(sock_fd); if (!h) { return NSAPI_ERROR_NO_SOCKET; } h->proto = proto; h->connected = false; h->callback = NULL; h->callback_data = NULL; //new up an int to store the socket fd *handle = h; return 0; } void W5500Interface::signal_event(nsapi_socket_t handle) { if (SKT(handle)->callback != NULL) { SKT(handle)->callback(SKT(handle)->callback_data); } } nsapi_error_t W5500Interface::socket_close(nsapi_socket_t handle) { if (handle == NULL) return 0; WIZnet_Chip::close(SKT(handle)->fd); SKT(handle)->fd = -1; return 0; } nsapi_error_t W5500Interface::socket_bind(nsapi_socket_t handle, const SocketAddress &address) { 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) { return NSAPI_ERROR_NO_SOCKET; } if (backlog != 1) { return NSAPI_ERROR_NO_SOCKET; } 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) { 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; //} nsapi_error_t err = WIZnet_Chip::sreg<uint8_t>(SKT(server)->fd, Sn_SR); if (err == SOCK_ESTABLISHED) { break; } } //get socket for the connection *handle = get_sock(SKT(server)->fd); if (!(*handle)) { error("No more socketa for binding"); return NSAPI_ERROR_NO_SOCKET; } //give it all of the socket info from the server 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); // 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 sockets 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) { 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; } int _size = WIZnet_Chip::wait_readable(SKT(handle)->fd, w5500_WAIT_TIMEOUT); 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) { if (handle == NULL) return; SKT(handle)->callback = callback; SKT(handle)->callback_data = data; }