Update UIPEthernet library

This commit is contained in:
Henrik Ekblad
2014-10-21 23:44:52 +02:00
parent f71ed97aaa
commit d5ca838371
8 changed files with 106 additions and 48 deletions
+2 -2
View File
@@ -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. 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! 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. 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 Additional information can be found on the Arduino website: http://www.arduino.cc/en/Hacking/Libraries
+21 -19
View File
@@ -226,6 +226,9 @@ newpacket:
goto newpacket; goto newpacket;
} }
ready: ready:
#if UIP_CLIENT_TIMER >= 0
u->timer = millis()+UIP_CLIENT_TIMER;
#endif
return size-remain; return size-remain;
} }
return -1; return -1;
@@ -326,6 +329,7 @@ UIPClient::flush()
void void
uipclient_appcall(void) uipclient_appcall(void)
{ {
uint16_t send_len = 0;
uip_userdata_t *u = (uip_userdata_t*)uip_conn->appstate; uip_userdata_t *u = (uip_userdata_t*)uip_conn->appstate;
if (!u && uip_connected()) if (!u && uip_connected())
{ {
@@ -357,17 +361,16 @@ uipclient_appcall(void)
#endif #endif
if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
{ {
memhandle newPacket = Enc28J60Network::allocBlock(uip_len); for (uint8_t i=0; i < UIP_SOCKET_NUMPACKETS; i++)
if (newPacket != NOBLOCK)
{ {
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) if (i == UIP_SOCKET_NUMPACKETS-1)
uip_stop(); 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; goto finish_newdata;
} }
} }
@@ -404,7 +407,7 @@ finish_newdata:
UIPClient::_dumpAllData(); UIPClient::_dumpAllData();
#endif #endif
uip_conn->appstate = NULL; uip_conn->appstate = NULL;
goto nodata; goto finish;
} }
if (uip_acked()) if (uip_acked())
{ {
@@ -422,26 +425,25 @@ finish_newdata:
{ {
if (u->packets_out[1] == NOBLOCK) if (u->packets_out[1] == NOBLOCK)
{ {
uip_len = u->out_pos; send_len = u->out_pos;
if (uip_len > 0) if (send_len > 0)
{ {
Enc28J60Network::resizeBlock(u->packets_out[0],0,uip_len); Enc28J60Network::resizeBlock(u->packets_out[0],0,send_len);
} }
} }
else else
uip_len = Enc28J60Network::blockSize(u->packets_out[0]); send_len = Enc28J60Network::blockSize(u->packets_out[0]);
if (uip_len > 0) if (send_len > 0)
{ {
UIPEthernetClass::uip_hdrlen = ((uint8_t*)uip_appdata)-uip_buf; 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) 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; UIPEthernetClass::packetstate |= UIPETHERNET_SENDPACKET;
uip_send(uip_appdata,uip_len);
} }
return;
} }
goto finish;
} }
} }
// don't close connection unless all outgoing packets are sent // don't close connection unless all outgoing packets are sent
@@ -470,9 +472,9 @@ finish_newdata:
} }
} }
} }
nodata: finish:
UIPEthernetClass::uip_packet = NOBLOCK; uip_send(uip_appdata,send_len);
uip_len=0; uip_len = send_len;
} }
uip_userdata_t * uip_userdata_t *
+3
View File
@@ -55,6 +55,9 @@ typedef struct {
memhandle packets_in[UIP_SOCKET_NUMPACKETS]; memhandle packets_in[UIP_SOCKET_NUMPACKETS];
memhandle packets_out[UIP_SOCKET_NUMPACKETS]; memhandle packets_out[UIP_SOCKET_NUMPACKETS];
memaddress out_pos; memaddress out_pos;
#if UIP_CLIENT_TIMER >= 0
unsigned long timer;
#endif
} uip_userdata_t; } uip_userdata_t;
class UIPClient : public Client { class UIPClient : public Client {
+44 -15
View File
@@ -45,7 +45,7 @@ uint8_t UIPEthernetClass::packetstate(0);
IPAddress UIPEthernetClass::_dnsServerAddress; IPAddress UIPEthernetClass::_dnsServerAddress;
DhcpClass* UIPEthernetClass::_dhcp(NULL); 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 // 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. // 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); Enc28J60Network::readPacket(in_packet,0,(uint8_t*)uip_buf,UIP_BUFSIZE);
if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_IP)) 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 #ifdef UIPETHERNET_DEBUG
Serial.print(F("readPacket type IP, uip_len: ")); Serial.print(F("readPacket type IP, uip_len: "));
Serial.println(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++) for (int i = 0; i < UIP_CONNS; i++)
{ {
uip_periodic(i); #endif
// If the above function invocation resulted in data that uip_conn = &uip_conns[i];
// should be sent out on the Enc28J60Network, the global variable #if UIP_CLIENT_TIMER >= 0
// uip_len is set to a value > 0. if (periodic)
if (uip_len > 0) {
{ #endif
uip_arp_out(); uip_process(UIP_TIMER);
network_send(); #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 #if UIP_UDP
for (int i = 0; i < UIP_UDP_CONNS; i++) for (int i = 0; i < UIP_UDP_CONNS; i++)
{ {
@@ -263,6 +291,7 @@ boolean UIPEthernetClass::network_send()
Serial.println(uip_hdrlen); Serial.println(uip_hdrlen);
#endif #endif
Enc28J60Network::writePacket(uip_packet,0,uip_buf,uip_hdrlen); Enc28J60Network::writePacket(uip_packet,0,uip_buf,uip_hdrlen);
packetstate &= ~ UIPETHERNET_SENDPACKET;
goto sendandfree; goto sendandfree;
} }
uip_packet = Enc28J60Network::allocBlock(uip_len); uip_packet = Enc28J60Network::allocBlock(uip_len);
@@ -286,7 +315,7 @@ sendandfree:
} }
void UIPEthernetClass::init(const uint8_t* mac) { 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); Enc28J60Network::init((uint8_t*)mac);
uip_seteth_addr(mac); uip_seteth_addr(mac);
+1 -1
View File
@@ -90,7 +90,7 @@ private:
static IPAddress _dnsServerAddress; static IPAddress _dnsServerAddress;
static DhcpClass* _dhcp; static DhcpClass* _dhcp;
static struct uip_timer periodic_timer; static unsigned long periodic_timer;
static void init(const uint8_t* mac); static void init(const uint8_t* mac);
static void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); static void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet);
@@ -155,7 +155,7 @@ Enc28J60Network::receivePacket()
// The above does not work. See Rev. B4 Silicon Errata point 6. // The above does not work. See Rev. B4 Silicon Errata point 6.
if (readReg(EPKTCNT) != 0) 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 // Set the read pointer to the start of the received packet
writeRegPair(ERDPTL, nextPacketPtr); writeRegPair(ERDPTL, nextPacketPtr);
// read the next packet pointer // read the next packet pointer
@@ -168,6 +168,20 @@ Enc28J60Network::receivePacket()
// read the receive status (see datasheet page 43) // read the receive status (see datasheet page 43)
rxstat = readOp(ENC28J60_READ_BUF_MEM, 0); rxstat = readOp(ENC28J60_READ_BUF_MEM, 0);
//rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; //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 // decrement the packet counter indicate we are done with this packet
writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
// check CRC and symbol errors (see datasheet page 44, table 7-3): // 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("sendPacket(");
Serial.print(handle); Serial.print(handle);
Serial.print(") ["); Serial.print(") [");
Serial.print(start); Serial.print(start,HEX);
Serial.print("-"); Serial.print("-");
Serial.print(end); Serial.print(end,HEX);
Serial.println("]:"); Serial.print("]: ");
for (uint16_t i=start; i<=end; i++) for (uint16_t i=start; i<=end; i++)
{ {
Serial.print(readByte(i),HEX); Serial.print(readByte(i),HEX);
@@ -248,7 +262,7 @@ uint16_t
Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len)
{ {
memblock *packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle]; 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); writeRegPair(ERDPTL, start);
@@ -313,7 +327,8 @@ Enc28J60Network::copyPacket(memhandle dest_pkt, memaddress dest_pos, memhandle s
{ {
memblock *dest = &blocks[dest_pkt]; memblock *dest = &blocks[dest_pkt];
memblock *src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_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 // Move the RX read pointer to the start of the next received packet
// This frees the memory we just read out // This frees the memory we just read out
setERXRDPT(); setERXRDPT();
+3 -2
View File
@@ -87,7 +87,7 @@ typedef unsigned short uip_stats_t;
* *
* \hideinitializer * \hideinitializer
*/ */
#define UIP_CONF_MAX_LISTENPORTS 4 #define UIP_CONF_MAX_LISTENPORTS 1
/** /**
* uIP buffer size. * uIP buffer size.
@@ -131,12 +131,13 @@ typedef unsigned short uip_stats_t;
*/ */
#define UIP_CONF_LOGGING 0 #define UIP_CONF_LOGGING 0
#define UIP_CONF_UDP 0
/** /**
* UDP support on or off * UDP support on or off
* (see uipethernet-conf.h) * (see uipethernet-conf.h)
* \hideinitializer * \hideinitializer
* *
* #define UIP_CONF_UDP 1
* *
* #define UIP_CONF_UDP_CONNS 4 * #define UIP_CONF_UDP_CONNS 4
*/ */
@@ -5,8 +5,9 @@
#define UIP_SOCKET_NUMPACKETS 5 #define UIP_SOCKET_NUMPACKETS 5
#define UIP_CONF_MAX_CONNECTIONS 4 #define UIP_CONF_MAX_CONNECTIONS 4
/* for UDP */ /* for UDP
#define UIP_CONF_UDP 0 * 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_BROADCAST 1
#define UIP_CONF_UDP_CONNS 4 #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...) */ * if set to a number <= 0 connect will timeout when uIP does (which might be longer than you expect...) */
#define UIP_CONNECT_TIMEOUT -1 #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 #endif