From d5ca838371ebb91c3cf36d48d29a8a4d63dcb012 Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Tue, 21 Oct 2014 23:44:52 +0200 Subject: [PATCH] Update UIPEthernet library --- libraries/UIPEthernet/README | 4 +- libraries/UIPEthernet/UIPClient.cpp | 40 +++++++------ libraries/UIPEthernet/UIPClient.h | 3 + libraries/UIPEthernet/UIPEthernet.cpp | 59 ++++++++++++++----- libraries/UIPEthernet/UIPEthernet.h | 2 +- .../UIPEthernet/utility/Enc28J60Network.cpp | 29 ++++++--- libraries/UIPEthernet/utility/uip-conf.h | 5 +- .../UIPEthernet/utility/uipethernet-conf.h | 12 +++- 8 files changed, 106 insertions(+), 48 deletions(-) diff --git a/libraries/UIPEthernet/README b/libraries/UIPEthernet/README index ec51f2d..321b334 100644 --- a/libraries/UIPEthernet/README +++ b/libraries/UIPEthernet/README @@ -1,4 +1,4 @@ -This is UIPEthernet version 1.07 +This is UIPEthernet version 1.09 An plugin-replacement of the stock Arduino Ethernet library for ENC28J60 shields and breakout boards. Full support for persistent (streaming) TCP-connections and UDP (Client and Server each), ARP, ICMP, DHCP and DNS. Just include 'UIPEthernet.h' instead of 'Ethernet.h' and use all your code written for the stock Arduino Ethernet lib! @@ -28,7 +28,7 @@ On a Mac, you will want to create a folder named "libraries" in in the "Document Or you download the zipped version of the library from https://github.com/ntruchsess/arduino_uip/releases, and copy the contained directory UIPEthernet to [path to Arduino distribution]\libraries\UIPEthernet. -If you are running Arduino-IDE 1.5.x use release-version 1.57 or checkout branch 'Arduino_1.5.5' +If you are running Arduino-IDE 1.5.x use release-version 1.59 or checkout branch 'Arduino_1.5.x' Additional information can be found on the Arduino website: http://www.arduino.cc/en/Hacking/Libraries diff --git a/libraries/UIPEthernet/UIPClient.cpp b/libraries/UIPEthernet/UIPClient.cpp index ffbb3e1..d199cfe 100644 --- a/libraries/UIPEthernet/UIPClient.cpp +++ b/libraries/UIPEthernet/UIPClient.cpp @@ -226,6 +226,9 @@ newpacket: goto newpacket; } ready: +#if UIP_CLIENT_TIMER >= 0 + u->timer = millis()+UIP_CLIENT_TIMER; +#endif return size-remain; } return -1; @@ -326,6 +329,7 @@ UIPClient::flush() void uipclient_appcall(void) { + uint16_t send_len = 0; uip_userdata_t *u = (uip_userdata_t*)uip_conn->appstate; if (!u && uip_connected()) { @@ -357,17 +361,16 @@ uipclient_appcall(void) #endif if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) { - memhandle newPacket = Enc28J60Network::allocBlock(uip_len); - if (newPacket != NOBLOCK) + for (uint8_t i=0; i < UIP_SOCKET_NUMPACKETS; i++) { - for (uint8_t i=0; i < UIP_SOCKET_NUMPACKETS; i++) + if (u->packets_in[i] == NOBLOCK) { - if (u->packets_in[i] == NOBLOCK) + u->packets_in[i] = Enc28J60Network::allocBlock(uip_len); + if (u->packets_in[i] != NOBLOCK) { + Enc28J60Network::copyPacket(u->packets_in[i],0,UIPEthernetClass::in_packet,((uint8_t*)uip_appdata)-uip_buf,uip_len); if (i == UIP_SOCKET_NUMPACKETS-1) uip_stop(); - Enc28J60Network::copyPacket(newPacket,0,UIPEthernetClass::in_packet,((uint8_t*)uip_appdata)-uip_buf,uip_len); - u->packets_in[i] = newPacket; goto finish_newdata; } } @@ -404,7 +407,7 @@ finish_newdata: UIPClient::_dumpAllData(); #endif uip_conn->appstate = NULL; - goto nodata; + goto finish; } if (uip_acked()) { @@ -422,26 +425,25 @@ finish_newdata: { if (u->packets_out[1] == NOBLOCK) { - uip_len = u->out_pos; - if (uip_len > 0) + send_len = u->out_pos; + if (send_len > 0) { - Enc28J60Network::resizeBlock(u->packets_out[0],0,uip_len); + Enc28J60Network::resizeBlock(u->packets_out[0],0,send_len); } } else - uip_len = Enc28J60Network::blockSize(u->packets_out[0]); - if (uip_len > 0) + send_len = Enc28J60Network::blockSize(u->packets_out[0]); + if (send_len > 0) { UIPEthernetClass::uip_hdrlen = ((uint8_t*)uip_appdata)-uip_buf; - UIPEthernetClass::uip_packet = Enc28J60Network::allocBlock(UIPEthernetClass::uip_hdrlen+uip_len); + UIPEthernetClass::uip_packet = Enc28J60Network::allocBlock(UIPEthernetClass::uip_hdrlen+send_len); if (UIPEthernetClass::uip_packet != NOBLOCK) { - Enc28J60Network::copyPacket(UIPEthernetClass::uip_packet,UIPEthernetClass::uip_hdrlen,u->packets_out[0],0,uip_len); + Enc28J60Network::copyPacket(UIPEthernetClass::uip_packet,UIPEthernetClass::uip_hdrlen,u->packets_out[0],0,send_len); UIPEthernetClass::packetstate |= UIPETHERNET_SENDPACKET; - uip_send(uip_appdata,uip_len); } - return; } + goto finish; } } // don't close connection unless all outgoing packets are sent @@ -470,9 +472,9 @@ finish_newdata: } } } -nodata: - UIPEthernetClass::uip_packet = NOBLOCK; - uip_len=0; + finish: + uip_send(uip_appdata,send_len); + uip_len = send_len; } uip_userdata_t * diff --git a/libraries/UIPEthernet/UIPClient.h b/libraries/UIPEthernet/UIPClient.h index ac601da..6c0c006 100644 --- a/libraries/UIPEthernet/UIPClient.h +++ b/libraries/UIPEthernet/UIPClient.h @@ -55,6 +55,9 @@ typedef struct { memhandle packets_in[UIP_SOCKET_NUMPACKETS]; memhandle packets_out[UIP_SOCKET_NUMPACKETS]; memaddress out_pos; +#if UIP_CLIENT_TIMER >= 0 + unsigned long timer; +#endif } uip_userdata_t; class UIPClient : public Client { diff --git a/libraries/UIPEthernet/UIPEthernet.cpp b/libraries/UIPEthernet/UIPEthernet.cpp index ea02c97..91ec70a 100644 --- a/libraries/UIPEthernet/UIPEthernet.cpp +++ b/libraries/UIPEthernet/UIPEthernet.cpp @@ -45,7 +45,7 @@ uint8_t UIPEthernetClass::packetstate(0); IPAddress UIPEthernetClass::_dnsServerAddress; DhcpClass* UIPEthernetClass::_dhcp(NULL); -struct uip_timer UIPEthernetClass::periodic_timer; +unsigned long UIPEthernetClass::periodic_timer; // Because uIP isn't encapsulated within a class we have to use global // variables, so we can only have one TCP/IP stack per program. @@ -183,7 +183,7 @@ UIPEthernetClass::tick() Enc28J60Network::readPacket(in_packet,0,(uint8_t*)uip_buf,UIP_BUFSIZE); if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_IP)) { - uip_packet = in_packet; + uip_packet = in_packet; //required for upper_layer_checksum of in_packet! #ifdef UIPETHERNET_DEBUG Serial.print(F("readPacket type IP, uip_len: ")); Serial.println(uip_len); @@ -220,22 +220,50 @@ UIPEthernetClass::tick() } } - if (uip_timer_expired(&periodic_timer)) + unsigned long now = millis(); + +#if UIP_CLIENT_TIMER >= 0 + boolean periodic = (long)( now - periodic_timer ) >= 0; + for (int i = 0; i < UIP_CONNS; i++) { - uip_timer_restart(&periodic_timer); +#else + if ((long)( now - periodic_timer ) >= 0) + { + periodic_timer = now + UIP_PERIODIC_TIMER; + for (int i = 0; i < UIP_CONNS; i++) { - uip_periodic(i); - // If the above function invocation resulted in data that - // should be sent out on the Enc28J60Network, the global variable - // uip_len is set to a value > 0. - if (uip_len > 0) - { - uip_arp_out(); - network_send(); - } +#endif + uip_conn = &uip_conns[i]; +#if UIP_CLIENT_TIMER >= 0 + if (periodic) + { +#endif + uip_process(UIP_TIMER); +#if UIP_CLIENT_TIMER >= 0 } - + else + { + if ((long)( now - ((uip_userdata_t*)uip_conn->appstate)->timer) >= 0) + uip_process(UIP_POLL_REQUEST); + else + continue; + } +#endif + // If the above function invocation resulted in data that + // should be sent out on the Enc28J60Network, the global variable + // uip_len is set to a value > 0. + if (uip_len > 0) + { + uip_arp_out(); + network_send(); + } + } +#if UIP_CLIENT_TIMER >= 0 + if (periodic) + { + periodic_timer = now + UIP_PERIODIC_TIMER; +#endif #if UIP_UDP for (int i = 0; i < UIP_UDP_CONNS; i++) { @@ -263,6 +291,7 @@ boolean UIPEthernetClass::network_send() Serial.println(uip_hdrlen); #endif Enc28J60Network::writePacket(uip_packet,0,uip_buf,uip_hdrlen); + packetstate &= ~ UIPETHERNET_SENDPACKET; goto sendandfree; } uip_packet = Enc28J60Network::allocBlock(uip_len); @@ -286,7 +315,7 @@ sendandfree: } void UIPEthernetClass::init(const uint8_t* mac) { - uip_timer_set(&periodic_timer, CLOCK_SECOND / 4); + periodic_timer = millis() + UIP_PERIODIC_TIMER; Enc28J60Network::init((uint8_t*)mac); uip_seteth_addr(mac); diff --git a/libraries/UIPEthernet/UIPEthernet.h b/libraries/UIPEthernet/UIPEthernet.h index 3bb18d4..c68d578 100644 --- a/libraries/UIPEthernet/UIPEthernet.h +++ b/libraries/UIPEthernet/UIPEthernet.h @@ -90,7 +90,7 @@ private: static IPAddress _dnsServerAddress; static DhcpClass* _dhcp; - static struct uip_timer periodic_timer; + static unsigned long periodic_timer; static void init(const uint8_t* mac); static void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); diff --git a/libraries/UIPEthernet/utility/Enc28J60Network.cpp b/libraries/UIPEthernet/utility/Enc28J60Network.cpp index fbef88d..c7c66fb 100644 --- a/libraries/UIPEthernet/utility/Enc28J60Network.cpp +++ b/libraries/UIPEthernet/utility/Enc28J60Network.cpp @@ -155,7 +155,7 @@ Enc28J60Network::receivePacket() // The above does not work. See Rev. B4 Silicon Errata point 6. if (readReg(EPKTCNT) != 0) { - uint16_t readPtr = nextPacketPtr+6; + uint16_t readPtr = nextPacketPtr+6 > RXSTOP_INIT ? nextPacketPtr+6-RXSTOP_INIT+RXSTART_INIT : nextPacketPtr+6; // Set the read pointer to the start of the received packet writeRegPair(ERDPTL, nextPacketPtr); // read the next packet pointer @@ -168,6 +168,20 @@ Enc28J60Network::receivePacket() // read the receive status (see datasheet page 43) rxstat = readOp(ENC28J60_READ_BUF_MEM, 0); //rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; +#ifdef ENC28J60DEBUG + Serial.print("receivePacket ["); + Serial.print(readPtr,HEX); + Serial.print("-"); + Serial.print((readPtr+len) % (RXSTOP_INIT+1),HEX); + Serial.print("], next: "); + Serial.print(nextPacketPtr,HEX); + Serial.print(", stat: "); + Serial.print(rxstat,HEX); + Serial.print(", count: "); + Serial.print(readReg(EPKTCNT)); + Serial.print(" -> "); + Serial.println((rxstat & 0x80)!=0 ? "OK" : "failed"); +#endif // decrement the packet counter indicate we are done with this packet writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); // check CRC and symbol errors (see datasheet page 44, table 7-3): @@ -215,10 +229,10 @@ Enc28J60Network::sendPacket(memhandle handle) Serial.print("sendPacket("); Serial.print(handle); Serial.print(") ["); - Serial.print(start); + Serial.print(start,HEX); Serial.print("-"); - Serial.print(end); - Serial.println("]:"); + Serial.print(end,HEX); + Serial.print("]: "); for (uint16_t i=start; i<=end; i++) { Serial.print(readByte(i),HEX); @@ -248,8 +262,8 @@ uint16_t Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) { memblock *packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle]; - memaddress start = packet->begin + position; - + memaddress start = handle == UIP_RECEIVEBUFFERHANDLE && packet->begin + position > RXSTOP_INIT ? packet->begin + position-RXSTOP_INIT+RXSTART_INIT : packet->begin + position; + writeRegPair(ERDPTL, start); if (len > packet->size - position) @@ -313,7 +327,8 @@ Enc28J60Network::copyPacket(memhandle dest_pkt, memaddress dest_pos, memhandle s { memblock *dest = &blocks[dest_pkt]; memblock *src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt]; - enc28J60_mempool_block_move_callback(dest->begin+dest_pos,src->begin+src_pos,len); + memaddress start = src_pkt == UIP_RECEIVEBUFFERHANDLE && src->begin + src_pos > RXSTOP_INIT ? src->begin + src_pos-RXSTOP_INIT+RXSTART_INIT : src->begin + src_pos; + enc28J60_mempool_block_move_callback(dest->begin+dest_pos,start,len); // Move the RX read pointer to the start of the next received packet // This frees the memory we just read out setERXRDPT(); diff --git a/libraries/UIPEthernet/utility/uip-conf.h b/libraries/UIPEthernet/utility/uip-conf.h index 814aeb9..e7f20d8 100644 --- a/libraries/UIPEthernet/utility/uip-conf.h +++ b/libraries/UIPEthernet/utility/uip-conf.h @@ -87,7 +87,7 @@ typedef unsigned short uip_stats_t; * * \hideinitializer */ -#define UIP_CONF_MAX_LISTENPORTS 4 +#define UIP_CONF_MAX_LISTENPORTS 1 /** * uIP buffer size. @@ -131,12 +131,13 @@ typedef unsigned short uip_stats_t; */ #define UIP_CONF_LOGGING 0 +#define UIP_CONF_UDP 0 /** * UDP support on or off * (see uipethernet-conf.h) * \hideinitializer * - * #define UIP_CONF_UDP 1 + * * #define UIP_CONF_UDP_CONNS 4 */ diff --git a/libraries/UIPEthernet/utility/uipethernet-conf.h b/libraries/UIPEthernet/utility/uipethernet-conf.h index 016e0e3..9dd8b27 100644 --- a/libraries/UIPEthernet/utility/uipethernet-conf.h +++ b/libraries/UIPEthernet/utility/uipethernet-conf.h @@ -5,8 +5,9 @@ #define UIP_SOCKET_NUMPACKETS 5 #define UIP_CONF_MAX_CONNECTIONS 4 -/* for UDP */ -#define UIP_CONF_UDP 0 +/* for UDP + * set UIP_CONF_UDP to 0 to disable UDP (saves aprox. 5kb flash) */ +#define UIP_CONF_UDP 1 #define UIP_CONF_BROADCAST 1 #define UIP_CONF_UDP_CONNS 4 @@ -18,4 +19,11 @@ * if set to a number <= 0 connect will timeout when uIP does (which might be longer than you expect...) */ #define UIP_CONNECT_TIMEOUT -1 +/* periodic timer for uip (in ms) */ +#define UIP_PERIODIC_TIMER 250 + +/* timer to poll client for data after last write (in ms) + * set to -1 to disable fast polling and rely on periodic only (saves 100 bytes flash) */ +#define UIP_CLIENT_TIMER 10 + #endif