Mbed library for ENC28J60 Ethernet modules. Full support for TCP/IP and UDP Server, Client and HTTP server (webserver). DHCP and DNS is included.
Dependents: mBuino_ENC28_MQTT Nucleo_Web_ENC28J60 Nucleo_Web_ENC28J60_ADC Serial_over_Ethernet ... more
Library for ENC28J60 Ethernet modules.
Ported to mbed from Norbert Truchsess's UIPEthernet library for Arduino. Thank you Norbert!
- Full support for persistent (streaming) TCP/IP and UDP connections Client and Server each, ARP, ICMP, DHCP and DNS.
- Works with both Mbed OS 2 and Mbed OS 5.
Usage:
- Import the library into your project.
- Add
#include "UipEthernet.h"
tomain.cpp
- Create one instance of the UipEthernet class initialized with the MAC address you'd like to use and SPI pins of the connected Mbed board.
Example programs:
Import programWebSwitch_ENC28J60
HTTP Server serving a simple webpage which enables to remotely turn a digital output on/off. Compile, download, run and type 'IP_address/secret/' (don't forget the last '/') into your web browser and hit ENTER.
Import programHTTPServer_Echo_ENC28J60
A simple HTTP server echoing received requests. Ethernet connection is over an ENC28J60 board. Usage: Type the server's IP address into you web browser and hit <ENTER>.
Import programTcpServer_ENC28J60
Simple TCP/IP Server using the UIPEthernet library for ENC28J60 Ethernet boards.
Import programTcpClient_ENC28J60
Simple TCP/IP Client using the UIPEthernet library for ENC28J60 Ethernet boards.
Import programUdpServer_ENC28J60
Simple UDP Server using the UIPEthernet library for ENC28J60 Ethernet boards.
Import programUdpClient_ENC28J60
Simple UDP Client using the UIPEthernet library for ENC28J60 Ethernet boards.
Import programMQTT_Hello_ENC28J60
MQTT Client example program. Ethernet connection is via an ENC28J60 module.
Revision 11:647d53d146f1, committed 2019-08-30
- Comitter:
- hudakz
- Date:
- Fri Aug 30 08:11:40 2019 +0000
- Parent:
- 10:e4ddab81e6a8
- Child:
- 12:1dd995402b99
- Commit message:
- "set_network" method of Mbed style added.
Changed in this revision
--- a/DhcpClient.h Tue Aug 27 22:08:54 2019 +0000 +++ b/DhcpClient.h Fri Aug 30 08:11:40 2019 +0000 @@ -1,7 +1,7 @@ // DHCP Library v0.3 - April 25, 2009 // Author: Jordan Terrell - blog.jordanterrell.com -#ifndef Dhcp_h -#define Dhcp_h +#ifndef DHCPCLIENT_h +#define DHCPCLIENT_h #include "UdpSocket.h" #include "IpAddress.h"
--- a/IpAddress.cpp Tue Aug 27 22:08:54 2019 +0000 +++ b/IpAddress.cpp Fri Aug 30 08:11:40 2019 +0000 @@ -18,7 +18,6 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - #include <stdio.h> #include "mbed.h" #include "IpAddress.h" @@ -29,7 +28,8 @@ * @param * @retval */ -IpAddress::IpAddress(void) { +IpAddress::IpAddress(void) +{ memset(_address, 0, sizeof(_address)); } @@ -39,7 +39,8 @@ * @param * @retval */ -IpAddress::IpAddress(uint8_t octet1, uint8_t octet2, uint8_t octet3, uint8_t octet4) { +IpAddress::IpAddress(uint8_t octet1, uint8_t octet2, uint8_t octet3, uint8_t octet4) +{ _address[0] = octet1; _address[1] = octet2; _address[2] = octet3; @@ -52,7 +53,8 @@ * @param * @retval */ -IpAddress::IpAddress(uint32_t address) { +IpAddress::IpAddress(uint32_t address) +{ memcpy(_address, &address, sizeof(_address)); } @@ -62,7 +64,8 @@ * @param * @retval */ -IpAddress::IpAddress(const uint8_t address[4]) { +IpAddress::IpAddress(const uint8_t address[4]) +{ memcpy(_address, address, sizeof(_address)); } @@ -72,10 +75,37 @@ * @param * @retval */ -//IPAddress &IPAddress::operator=(const uint8_t* address) { -// memcpy(_address, address, sizeof(_address)); -// return *this; -//} +IpAddress::IpAddress(const char* str, size_t len) +{ + uint8_t pos = 0; + uint8_t byte; + uint8_t i = 0; + + if (len > 16) + return; + + while (true) { + if (pos == len || str[pos] < '0' || str[pos] > '9') { + return; + } + + byte = 0; + while (pos < len && str[pos] >= '0' && str[pos] <= '9') { + byte *= 10; + byte += str[pos++] - '0'; + } + + _address[i++] = byte; + + if (i == 4) { + return; + } + + if (pos == len || str[pos++] != '.') { + return; + } + } +} /** * @brief @@ -83,7 +113,19 @@ * @param * @retval */ -IpAddress &IpAddress::operator=(uint32_t address) { +IpAddress &IpAddress::operator=(const uint8_t* address) { + memcpy(_address, address, sizeof(_address)); + return *this; +} + +/** + * @brief + * @note + * @param + * @retval + */ +IpAddress &IpAddress::operator=(uint32_t address) +{ memcpy(_address, (const uint8_t*) &address, sizeof(_address)); return *this; } @@ -105,9 +147,10 @@ * @param * @retval */ -const char* IpAddress::toString(char* buf) { - uint8_t i = 0; - uint8_t j = 0; +const char* IpAddress::toString(char* buf) +{ + uint8_t i = 0; + uint8_t j = 0; for (i = 0; i < 3; i++) { j += sprintf(&buf[j], "%d", _address[i]);
--- a/IpAddress.h Tue Aug 27 22:08:54 2019 +0000 +++ b/IpAddress.h Fri Aug 30 08:11:40 2019 +0000 @@ -18,8 +18,8 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef IPADDRESS_H -#define IPADDRESS_H +#ifndef IPADDRESS_h +#define IPADDRESS_h #include <stdio.h> @@ -36,6 +36,7 @@ IpAddress(uint8_t octet1, uint8_t octet2, uint8_t octet3, uint8_t octet4); IpAddress(uint32_t address); IpAddress(const uint8_t address[4]); + IpAddress(const char *str, size_t len); // Overloaded cast operator to allow IPAddress objects to be used where a pointer // to a four-byte uint8_t array is expected @@ -49,6 +50,7 @@ // Overloaded copy operators to allow initialisation of IPAddress objects from other types IpAddress &operator =(uint32_t address); + IpAddress &operator =(const uint8_t* address); // Returns IP Address as string of char const char* toString(char* buf); @@ -59,7 +61,6 @@ // stored. uint8_t* rawAddress(void) { return _address; } - // virtual size_t printTo(Print& p) const; friend class UIPEthernet; friend class UdpSocket; friend class TcpClient;
--- a/TcpClient.cpp Tue Aug 27 22:08:54 2019 +0000 +++ b/TcpClient.cpp Fri Aug 30 08:11:40 2019 +0000 @@ -31,7 +31,7 @@ #define UIP_TCP_PHYH_LEN UIP_LLH_LEN + UIP_IPTCPH_LEN -uip_userdata_t TcpClient:: all_data[UIP_CONNS]; +uip_userdata_t TcpClient::all_data[UIP_CONNS]; /** * @brief @@ -194,7 +194,7 @@ * @param * @retval */ -size_t TcpClient::send(uint8_t c) +int TcpClient::send(uint8_t c) { return _write(data, &c, 1); } @@ -205,7 +205,7 @@ * @param * @retval */ -size_t TcpClient::send(const uint8_t* buf, size_t size) +int TcpClient::send(const uint8_t* buf, size_t size) { return _write(data, buf, size); } @@ -216,9 +216,9 @@ * @param * @retval */ -size_t TcpClient::_write(uip_userdata_t* data, const uint8_t* buf, size_t size) +int TcpClient::_write(uip_userdata_t* data, const uint8_t* buf, size_t size) { - int remain = size; + size_t remain = size; uint16_t written; #if UIP_ATTEMPTS_ON_WRITE > 0 uint16_t attempts = UIP_ATTEMPTS_ON_WRITE; @@ -229,7 +229,7 @@ if (data->packets_out[p] == NOBLOCK) { newpacket: - data->packets_out[p] = UipEthernet::ethernet->phy.allocBlock(UIP_SOCKET_DATALEN); + data->packets_out[p] = UipEthernet::ethernet->enc28j60Eth.allocBlock(UIP_SOCKET_DATALEN); if (data->packets_out[p] == NOBLOCK) { #if UIP_ATTEMPTS_ON_WRITE > 0 @@ -254,7 +254,7 @@ remain ); #endif - written = UipEthernet::ethernet->phy.writePacket + written = UipEthernet::ethernet->enc28j60Eth.writePacket ( data->packets_out[p], data->out_pos, @@ -310,7 +310,7 @@ { size_t len = 0; for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) { - len += UipEthernet::ethernet->phy.blockSize(u->packets_in[i]); + len += UipEthernet::ethernet->enc28j60Eth.blockSize(u->packets_in[i]); } return len; @@ -331,8 +331,8 @@ uint16_t read; do { - read = UipEthernet::ethernet->phy.readPacket(data->packets_in[0], 0, buf + size - remain, remain); - if (read == UipEthernet::ethernet->phy.blockSize(data->packets_in[0])) { + read = UipEthernet::ethernet->enc28j60Eth.readPacket(data->packets_in[0], 0, buf + size - remain, remain); + if (read == UipEthernet::ethernet->enc28j60Eth.blockSize(data->packets_in[0])) { remain -= read; _eatBlock(&data->packets_in[0]); if @@ -350,7 +350,7 @@ } } else { - UipEthernet::ethernet->phy.resizeBlock(data->packets_in[0], read); + UipEthernet::ethernet->enc28j60Eth.resizeBlock(data->packets_in[0], read); break; } } while (remain > 0); @@ -366,7 +366,7 @@ * @param * @retval */ -size_t TcpClient::recv() +int TcpClient::recv() { static uint8_t c; if (recv(&c, 1) < 0) @@ -385,7 +385,7 @@ static uint8_t c; if (*this) { if (data->packets_in[0] != NOBLOCK) { - UipEthernet::ethernet->phy.readPacket(data->packets_in[0], 0, &c, 1); + UipEthernet::ethernet->enc28j60Eth.readPacket(data->packets_in[0], 0, &c, 1); return c; } } @@ -412,12 +412,9 @@ * @param * @retval */ -const char* TcpClient::getpeername() +IpAddress TcpClient::getRemoteIp() { - static char buf[16]; - IpAddress remoteIp = ip_addr_uip(data->ripaddr); - - return remoteIp.toString(buf); + return ip_addr_uip(data->ripaddr); } /** @@ -426,9 +423,11 @@ * @param * @retval */ -IpAddress TcpClient::getRemoteIp() +const char* TcpClient::getpeername() { - return ip_addr_uip(data->ripaddr); + static char buf[16]; + + return getRemoteIp().toString(buf); } /** @@ -481,9 +480,9 @@ if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) { for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) { if (u->packets_in[i] == NOBLOCK) { - u->packets_in[i] = UipEthernet::ethernet->phy.allocBlock(uip_len); + u->packets_in[i] = UipEthernet::ethernet->enc28j60Eth.allocBlock(uip_len); if (u->packets_in[i] != NOBLOCK) { - UipEthernet::ethernet->phy.copyPacket + UipEthernet::ethernet->enc28j60Eth.copyPacket ( u->packets_in[i], 0, @@ -552,16 +551,16 @@ if (u->packets_out[1] == NOBLOCK) { send_len = u->out_pos; if (send_len > 0) { - UipEthernet::ethernet->phy.resizeBlock(u->packets_out[0], 0, send_len); + UipEthernet::ethernet->enc28j60Eth.resizeBlock(u->packets_out[0], 0, send_len); } } else - send_len = UipEthernet::ethernet->phy.blockSize(u->packets_out[0]); + send_len = UipEthernet::ethernet->enc28j60Eth.blockSize(u->packets_out[0]); if (send_len > 0) { UipEthernet::uipHeaderLen = ((uint8_t*)uip_appdata) - uip_buf; - UipEthernet::uipPacket = UipEthernet::ethernet->phy.allocBlock(UipEthernet::uipHeaderLen + send_len); + UipEthernet::uipPacket = UipEthernet::ethernet->enc28j60Eth.allocBlock(UipEthernet::uipHeaderLen + send_len); if (UipEthernet::uipPacket != NOBLOCK) { - UipEthernet::ethernet->phy.copyPacket + UipEthernet::ethernet->enc28j60Eth.copyPacket ( UipEthernet::uipPacket, UipEthernet::uipHeaderLen, @@ -620,6 +619,8 @@ if (!data->state) { data->pollTimer.reset(); data->state = sock | UIP_CLIENT_CONNECTED; + data->ripaddr[0] = 0; + data->ripaddr[1] = 0; memset(data->packets_in, 0, sizeof(data->packets_in) / sizeof(data->packets_in[0])); memset(&data->packets_out, 0, sizeof(data->packets_out) / sizeof(data->packets_out[0])); data->out_pos = 0; @@ -663,7 +664,7 @@ printf("-> "); #endif - UipEthernet::ethernet->phy.freeBlock(block[0]); + UipEthernet::ethernet->enc28j60Eth.freeBlock(block[0]); for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS - 1; i++) { block[i] = block[i + 1]; } @@ -687,7 +688,7 @@ void TcpClient::_flushBlocks(memhandle* block) { for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) { - UipEthernet::ethernet->phy.freeBlock(block[i]); + UipEthernet::ethernet->enc28j60Eth.freeBlock(block[i]); block[i] = NOBLOCK; } }
--- a/TcpClient.h Tue Aug 27 22:08:54 2019 +0000 +++ b/TcpClient.h Fri Aug 30 08:11:40 2019 +0000 @@ -16,8 +16,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef UIPCLIENT_H -#define UIPCLIENT_H +#ifndef TCPCLIENT_h +#define TCPCLIENT_h #include "mbed.h" #include "IpAddress.h" @@ -74,10 +74,10 @@ operator bool(); virtual bool operator ==(const TcpClient& ); virtual bool operator !=(const TcpClient& rhs) { return !this->operator ==(rhs); } - size_t send(uint8_t); - size_t send(const uint8_t* buf, size_t size); + int send(uint8_t); + int send(const uint8_t* buf, size_t size); size_t available(); - size_t recv(); + int recv(); int peek(); void flush(); const char* getpeername(); @@ -85,7 +85,7 @@ void close(); static uip_userdata_t all_data[UIP_CONNS]; - static size_t _write(uip_userdata_t* , const uint8_t* buf, size_t size); + static int _write(uip_userdata_t* , const uint8_t* buf, size_t size); protected: uint8_t* rawIPAddress(IpAddress& addr) { return addr.rawAddress(); }
--- a/TcpServer.cpp Tue Aug 27 22:08:54 2019 +0000 +++ b/TcpServer.cpp Fri Aug 30 08:11:40 2019 +0000 @@ -28,8 +28,9 @@ * @param * @retval */ -TcpServer::TcpServer() -{ } +TcpServer::TcpServer() : + _conns(1) +{} /** * @brief @@ -40,7 +41,7 @@ TcpClient* TcpServer::accept() { UipEthernet::ethernet->tick(); - for (uip_userdata_t * data = &TcpClient::all_data[0]; data < &TcpClient::all_data[UIP_CONNS]; data++) { + for (uip_userdata_t * data = &TcpClient::all_data[0]; data < &TcpClient::all_data[_conns]; data++) { if ( data->packets_in[0] != NOBLOCK && @@ -65,7 +66,10 @@ * @retval */ void TcpServer::open(UipEthernet* ethernet) -{ } +{ + if (UipEthernet::ethernet != ethernet) + UipEthernet::ethernet = ethernet; +} /** * @brief @@ -122,7 +126,7 @@ size_t TcpServer::send(const uint8_t* buf, size_t size) { size_t ret = 0; - for (uip_userdata_t * data = &TcpClient::all_data[0]; data < &TcpClient::all_data[UIP_CONNS]; data++) { + for (uip_userdata_t * data = &TcpClient::all_data[0]; data < &TcpClient::all_data[_conns]; data++) { if ((data->state & UIP_CLIENT_CONNECTED) && uip_conns[data->state & UIP_CLIENT_SOCKETS].lport == _port) ret += TcpClient::_write(data, buf, size); }
--- a/TcpServer.h Tue Aug 27 22:08:54 2019 +0000 +++ b/TcpServer.h Fri Aug 30 08:11:40 2019 +0000 @@ -16,8 +16,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef UIPSERVER_H -#define UIPSERVER_H +#ifndef TCPSERVER_h +#define TCPSERVER_h #include "TcpClient.h"
--- a/UdpSocket.cpp Tue Aug 27 22:08:54 2019 +0000 +++ b/UdpSocket.cpp Fri Aug 30 08:11:40 2019 +0000 @@ -60,9 +60,9 @@ uip_udp_remove(_uip_udp_conn); _uip_udp_conn->appstate = NULL; _uip_udp_conn = NULL; - UipEthernet::ethernet->phy.freeBlock(appdata.packet_in); - UipEthernet::ethernet->phy.freeBlock(appdata.packet_next); - UipEthernet::ethernet->phy.freeBlock(appdata.packet_out); + UipEthernet::ethernet->enc28j60Eth.freeBlock(appdata.packet_in); + UipEthernet::ethernet->enc28j60Eth.freeBlock(appdata.packet_next); + UipEthernet::ethernet->enc28j60Eth.freeBlock(appdata.packet_out); memset(&appdata, 0, sizeof(appdata)); } } @@ -109,7 +109,7 @@ if (_uip_udp_conn) { if (appdata.packet_out == NOBLOCK) { - appdata.packet_out = UipEthernet::ethernet->phy.allocBlock(UIP_UDP_MAXPACKETSIZE); + appdata.packet_out = UipEthernet::ethernet->enc28j60Eth.allocBlock(UIP_UDP_MAXPACKETSIZE); appdata.out_pos = UIP_UDP_PHYH_LEN; if (appdata.packet_out != NOBLOCK) return 1; @@ -155,7 +155,7 @@ { if (_uip_udp_conn && appdata.packet_out != NOBLOCK) { appdata.send = true; - UipEthernet::ethernet->phy.resizeBlock(appdata.packet_out, 0, appdata.out_pos); + UipEthernet::ethernet->enc28j60Eth.resizeBlock(appdata.packet_out, 0, appdata.out_pos); uip_udp_periodic_conn(_uip_udp_conn); if (uip_len > 0) { _send(&appdata); @@ -176,7 +176,7 @@ size_t UdpSocket::write(const uint8_t* buffer, size_t size) { if (appdata.packet_out != NOBLOCK) { - size_t ret = UipEthernet::ethernet->phy.writePacket + size_t ret = UipEthernet::ethernet->enc28j60Eth.writePacket ( appdata.packet_out, appdata.out_pos, @@ -201,7 +201,7 @@ printf("udp parsePacket freeing previous packet: %d\r\n", appdata.packet_in); } #endif - UipEthernet::ethernet->phy.freeBlock(appdata.packet_in); + UipEthernet::ethernet->enc28j60Eth.freeBlock(appdata.packet_in); appdata.packet_in = appdata.packet_next; appdata.packet_next = NOBLOCK; @@ -212,7 +212,7 @@ } #endif - int size = UipEthernet::ethernet->phy.blockSize(appdata.packet_in); + int size = UipEthernet::ethernet->enc28j60Eth.blockSize(appdata.packet_in); #ifdef UIPETHERNET_DEBUG_UDP if (appdata.packet_in != NOBLOCK) { printf(", size: %d\r\n", size); @@ -225,7 +225,7 @@ int UdpSocket::available() { UipEthernet::ethernet->tick(); - return UipEthernet::ethernet->phy.blockSize(appdata.packet_in); + return UipEthernet::ethernet->enc28j60Eth.blockSize(appdata.packet_in); } // Read a single byte from the current packet @@ -246,13 +246,13 @@ { UipEthernet::ethernet->tick(); if (appdata.packet_in != NOBLOCK) { - memaddress read = UipEthernet::ethernet->phy.readPacket(appdata.packet_in, 0, buffer, len); - if (read == UipEthernet::ethernet->phy.blockSize(appdata.packet_in)) { - UipEthernet::ethernet->phy.freeBlock(appdata.packet_in); + memaddress read = UipEthernet::ethernet->enc28j60Eth.readPacket(appdata.packet_in, 0, buffer, len); + if (read == UipEthernet::ethernet->enc28j60Eth.blockSize(appdata.packet_in)) { + UipEthernet::ethernet->enc28j60Eth.freeBlock(appdata.packet_in); appdata.packet_in = NOBLOCK; } else - UipEthernet::ethernet->phy.resizeBlock(appdata.packet_in, read); + UipEthernet::ethernet->enc28j60Eth.resizeBlock(appdata.packet_in, read); return read; } @@ -265,7 +265,7 @@ UipEthernet::ethernet->tick(); if (appdata.packet_in != NOBLOCK) { unsigned char c; - if (UipEthernet::ethernet->phy.readPacket(appdata.packet_in, 0, &c, 1) == 1) + if (UipEthernet::ethernet->enc28j60Eth.readPacket(appdata.packet_in, 0, &c, 1) == 1) return c; } @@ -276,7 +276,7 @@ void UdpSocket::flush() { UipEthernet::ethernet->tick(); - UipEthernet::ethernet->phy.freeBlock(appdata.packet_in); + UipEthernet::ethernet->enc28j60Eth.freeBlock(appdata.packet_in); appdata.packet_in = NOBLOCK; } @@ -300,18 +300,18 @@ if (data->packet_next == NOBLOCK) { uip_udp_conn->rport = UDPBUF->srcport; uip_ipaddr_copy(uip_udp_conn->ripaddr, UDPBUF->srcipaddr); - data->packet_next = UipEthernet::ethernet->phy.allocBlock(ntohs(UDPBUF->udplen) - UIP_UDPH_LEN); + data->packet_next = UipEthernet::ethernet->enc28j60Eth.allocBlock(ntohs(UDPBUF->udplen) - UIP_UDPH_LEN); //if we are unable to allocate memory the packet is dropped. udp doesn't guarantee packet delivery if (data->packet_next != NOBLOCK) { //discard Linklevel and IP and udp-header and any trailing bytes: - UipEthernet::ethernet->phy.copyPacket + UipEthernet::ethernet->enc28j60Eth.copyPacket ( data->packet_next, 0, UipEthernet::inPacket, UIP_UDP_PHYH_LEN, - UipEthernet::ethernet->phy.blockSize(data->packet_next) + UipEthernet::ethernet->enc28j60Eth.blockSize(data->packet_next) ); #ifdef UIPETHERNET_DEBUG_UDP printf
--- a/UdpSocket.h Tue Aug 27 22:08:54 2019 +0000 +++ b/UdpSocket.h Fri Aug 30 08:11:40 2019 +0000 @@ -18,8 +18,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef UIPUDP_H -#define UIPUDP_H +#ifndef UDPSOCKET_h +#define UDPSOCKET_h #include "mbed.h" #include "utility/Udp.h"
--- a/UipEthernet.cpp Tue Aug 27 22:08:54 2019 +0000 +++ b/UipEthernet.cpp Fri Aug 30 08:11:40 2019 +0000 @@ -20,7 +20,7 @@ */ #include "mbed.h" #include "UipEthernet.h" -#include "utility/Enc28j60Py.h" +#include "utility/Enc28j60Eth.h" #include "UdpSocket.h" extern "C" @@ -38,7 +38,6 @@ uint8_t UipEthernet:: uipHeaderLen(0); uint8_t UipEthernet:: packetState(0); IpAddress UipEthernet:: dnsServerAddress; -//DhcpClient UIPEthernet:: dhcpClient; /** * @brief @@ -48,9 +47,9 @@ */ void enc28j60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) { - //as ENC28J60 DMA is unable to copy single bytes: + //as ENC28J60 DMA is unable to copy single byte: if (len == 1) { - UipEthernet::ethernet->phy.writeByte(dest, UipEthernet::ethernet->phy.readByte(src)); + UipEthernet::ethernet->enc28j60Eth.writeByte(dest, UipEthernet::ethernet->enc28j60Eth.readByte(src)); } else { // calculate address of last byte @@ -70,25 +69,25 @@ prevent a never ending DMA operation which would overwrite the entire 8-Kbyte buffer. */ - UipEthernet::ethernet->phy.writeRegPair(EDMASTL, src); - UipEthernet::ethernet->phy.writeRegPair(EDMADSTL, dest); + UipEthernet::ethernet->enc28j60Eth.writeRegPair(EDMASTL, src); + UipEthernet::ethernet->enc28j60Eth.writeRegPair(EDMADSTL, dest); - if ((src <= RXSTOP_INIT) && (len > RXSTOP_INIT)) - len -= (RXSTOP_INIT - RXSTART_INIT); - UipEthernet::ethernet->phy.writeRegPair(EDMANDL, len); + if ((src <= RXEND_INIT) && (len > RXEND_INIT)) + len -= ((RXEND_INIT + 1) - RXSTART_INIT); + UipEthernet::ethernet->enc28j60Eth.writeRegPair(EDMANDL, len); /* 2. If an interrupt at the end of the copy process is desired, set EIE.DMAIE and EIE.INTIE and clear EIR.DMAIF. 3. Verify that ECON1.CSUMEN is clear. */ - UipEthernet::ethernet->phy.writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); + UipEthernet::ethernet->enc28j60Eth.writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); /* 4. Start the DMA copy by setting ECON1.DMAST. */ - UipEthernet::ethernet->phy.writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); + UipEthernet::ethernet->enc28j60Eth.writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); // wait until runnig DMA is completed - while (UipEthernet::ethernet->phy.readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST); + while (UipEthernet::ethernet->enc28j60Eth.readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST); } } @@ -97,7 +96,7 @@ * variables, so we can only have one TCP/IP stack per program. */ UipEthernet::UipEthernet(const uint8_t mac[6], PinName mosi, PinName miso, PinName sck, PinName cs) : - phy(mosi, miso, sck, cs), + enc28j60Eth(mosi, miso, sck, cs), _mac(new uint8_t[6]), _ip(), _dns(), @@ -108,8 +107,6 @@ _mac[i] = mac[i]; } -#if UIP_UDP - /** * @brief * @note @@ -147,7 +144,22 @@ return 1; } } -#endif + +/** + * @brief + * @note + * @param + * @retval + */ +void UipEthernet::set_network(const char *ip_address, const char *netmask, const char *gateway) +{ + _ip = IpAddress(ip_address, strlen(ip_address)); + _dns = _ip; + _dns[3] = 1; + _gateway = IpAddress(gateway, strlen(gateway)); + _subnet = IpAddress(netmask, strlen(netmask)); + set_network(_ip, _dns, _gateway, _subnet); +} /** * @brief @@ -202,6 +214,7 @@ _dns = dns; _gateway = gateway; _subnet = IpAddress(255, 255, 255, 0); + set_network(_ip, _dns, _gateway, _subnet); } /** @@ -324,7 +337,7 @@ void UipEthernet::tick() { if (inPacket == NOBLOCK) { - inPacket = phy.receivePacket(); + inPacket = enc28j60Eth.receivePacket(); #ifdef UIPETHERNET_DEBUG if (in_packet != NOBLOCK) { printf("--------------\r\nreceivePacket: %d\r\n", in_packet); @@ -334,9 +347,9 @@ if (inPacket != NOBLOCK) { packetState = UIPETHERNET_FREEPACKET; - uip_len = phy.blockSize(inPacket); + uip_len = enc28j60Eth.blockSize(inPacket); if (uip_len > 0) { - phy.readPacket(inPacket, 0, (uint8_t*)uip_buf, UIP_BUFSIZE); + enc28j60Eth.readPacket(inPacket, 0, (uint8_t*)uip_buf, UIP_BUFSIZE); if (ETH_HDR->type == HTONS(UIP_ETHTYPE_IP)) { uipPacket = inPacket; //required for upper_layer_checksum of in_packet! #ifdef UIPETHERNET_DEBUG @@ -367,7 +380,7 @@ #ifdef UIPETHERNET_DEBUG printf("freeing packet: %d\r\n", in_packet); #endif - phy.freePacket(); + enc28j60Eth.freePacket(); inPacket = NOBLOCK; } } @@ -431,25 +444,25 @@ #ifdef UIPETHERNET_DEBUG printf("Enc28J60Network_send uip_packet: %d, hdrlen: %d\r\n", uip_packet, uip_hdrlen); #endif - phy.writePacket(uipPacket, 0, uip_buf, uipHeaderLen); + enc28j60Eth.writePacket(uipPacket, 0, uip_buf, uipHeaderLen); packetState &= ~UIPETHERNET_SENDPACKET; goto sendandfree; } - uipPacket = Enc28j60Phy::allocBlock(uip_len); + uipPacket = Enc28j60Eth::allocBlock(uip_len); if (uipPacket != NOBLOCK) { #ifdef UIPETHERNET_DEBUG printf("Enc28J60Network_send uip_buf (uip_len): %d, packet: %d\r\n", uip_len, uip_packet); #endif - phy.writePacket(uipPacket, 0, uip_buf, uip_len); + enc28j60Eth.writePacket(uipPacket, 0, uip_buf, uip_len); goto sendandfree; } return false; sendandfree: - phy.sendPacket(uipPacket); - Enc28j60Phy::freeBlock(uipPacket); + enc28j60Eth.sendPacket(uipPacket); + Enc28j60Eth::freeBlock(uipPacket); uipPacket = NOBLOCK; return true; } @@ -464,7 +477,7 @@ { periodicTimer.start(); - phy.init((uint8_t*)mac); + enc28j60Eth.init((uint8_t*)mac); uip_seteth_addr(mac); uip_init(); @@ -599,7 +612,7 @@ ); #endif if (upper_layer_memlen < upper_layer_len) { - sum = phy.chksum + sum = enc28j60Eth.chksum ( sum, UipEthernet::uipPacket, UIP_IPH_LEN + UIP_LLH_LEN + @@ -658,4 +671,5 @@ return sum; } + #endif
--- a/UipEthernet.h Tue Aug 27 22:08:54 2019 +0000 +++ b/UipEthernet.h Fri Aug 30 08:11:40 2019 +0000 @@ -18,8 +18,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef UIPETHERNET_H -#define UIPETHERNET_H +#ifndef UIPETHERNET_h +#define UIPETHERNET_h //#define UIPETHERNET_DEBUG //#define UIPETHERNET_DEBUG_CHKSUM @@ -28,7 +28,7 @@ #include "mbed.h" #include "DhcpClient.h" #include "IpAddress.h" -#include "utility/Enc28j60Py.h" +#include "utility/Enc28j60Eth.h" #include "TcpClient.h" #include "TcpServer.h" #include "UdpSocket.h" @@ -64,7 +64,7 @@ public: static UipEthernet* ethernet; static IpAddress dnsServerAddress; - Enc28j60Phy phy; + Enc28j60Eth enc28j60Eth; UipEthernet (const uint8_t mac[6], PinName mosi, PinName miso, PinName sck, PinName cs); @@ -74,6 +74,7 @@ void set_network(IpAddress ip, IpAddress dns); void set_network(IpAddress ip, IpAddress dns, IpAddress gateway); void set_network(IpAddress ip, IpAddress dns, IpAddress gateway, IpAddress subnet); + void set_network(const char *ip_address, const char *netmask, const char *gateway); void tick(); IpAddress localIP(); IpAddress subnetMask(); @@ -84,6 +85,7 @@ const char* get_gateway(); static uint16_t chksum(uint16_t sum, const uint8_t* data, uint16_t len); static uint16_t ipchksum(); + bool stoip4(const char *ip4addr, size_t len, void *dest); private: uint8_t *const _mac; IpAddress _ip; @@ -114,4 +116,5 @@ uint16_t uip_icmp6chksum(); #endif }; + #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utility/Enc28j60Eth.cpp Fri Aug 30 08:11:40 2019 +0000 @@ -0,0 +1,734 @@ +/* + Enc28J60Network.cpp + UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. + + Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> + All rights reserved. + + based on enc28j60.c file from the AVRlib library by Pascal Stang. + For AVRlib See http://www.procyonengineering.com/ + + Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include "Enc28j60Eth.h" +#include "mbed.h" + +extern "C" +{ +#include "enc28j60.h" +#include "uip.h" +} + +// Static member initialization +uint16_t Enc28j60Eth::nextPacketPtr; +uint8_t Enc28j60Eth::bank = 0xff; +struct memblock Enc28j60Eth::receivePkt; + +/** + * @brief + * @note + * @param + * @retval + */ +Enc28j60Eth::Enc28j60Eth(PinName mosi, PinName miso, PinName sclk, PinName cs) : + MemPool(), + _spi(mosi, miso, sclk), + _cs(cs) +{ } + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::init(uint8_t* macaddr) +{ + MemPool::init(); // 1 byte in between RX_STOP_INIT and pool to allow prepending of controlbyte + // initialize SPI interface + _spi.format(8, 0); // 8-bit, mode 0 + _spi.frequency(20000000); // 20 Mbit/s + wait_ms(1000); // 1 second for stable state + // Release SPI + _cs = 1; + + // perform system reset + writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); + + // check CLKRDY bit to see if reset is complete + //while(!(readReg(ESTAT) & ESTAT_CLKRDY)); + // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait. + wait_ms(50); + + // do bank 0 stuff + // initialize receive buffer + // 16-bit transfers, must write low byte first + // set receive buffer start address + nextPacketPtr = RXSTART_INIT; + + // Rx start + writeRegPair(ERXSTL, RXSTART_INIT); + + // set receive pointer address + writeRegPair(ERXRDPTL, RXSTART_INIT); + + // RX end + writeRegPair(ERXNDL, RXEND_INIT); + + //All memory which is not used by the receive buffer is considered the transmission buffer. + // No explicit action is required to initialize the transmission buffer. + // However, he host controller should leave at least seven bytes between each + // packet and the beginning of the receive buffer. + // TX start + //writeRegPair(ETXSTL, TXSTART_INIT); + // TX end + //writeRegPair(ETXNDL, TXEND_INIT); + + // do bank 1 stuff, packet filter: + // For broadcast packets we allow only ARP packtets + // All other packets should be unicast only for our mac (MAADR) + // + // The pattern to match on is therefore + // Type ETH.DST + // ARP BROADCAST + // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9 + // in binary these poitions are:11 0000 0011 1111 + // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 + //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN! + writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN | ERXFCON_BCEN); + writeRegPair(EPMM0, 0x303f); + writeRegPair(EPMCSL, 0xf7f9); + + // + // + // do bank 2 stuff, + // enable MAC receive + // and bring MAC out of reset (writes 0x00 to MACON2) + writeRegPair(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS); + + // enable automatic padding to 60bytes and CRC operations + writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN); + + // set inter-frame gap (non-back-to-back) + writeRegPair(MAIPGL, 0x0C12); + + // set inter-frame gap (back-to-back) + writeReg(MABBIPG, 0x12); + + // Set the maximum packet size which the controller will accept + // Do not send packets longer than MAX_FRAMELEN: + writeRegPair(MAMXFLL, MAX_FRAMELEN); + + // do bank 3 stuff + // write MAC address + // NOTE: MAC address in ENC28J60 is byte-backward + writeReg(MAADR5, macaddr[0]); + writeReg(MAADR4, macaddr[1]); + writeReg(MAADR3, macaddr[2]); + writeReg(MAADR2, macaddr[3]); + writeReg(MAADR1, macaddr[4]); + writeReg(MAADR0, macaddr[5]); + + // no loopback of transmitted frames + phyWrite(PHCON2, PHCON2_HDLDIS); + + // switch to bank 0 + setBank(ECON1); + + // enable interrutps + writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE); + + // enable packet reception + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); + + //Configure leds + phyWrite(PHLCON, 0x476); +} + +/** + * @brief + * @note + * @param + * @retval + */ +memhandle Enc28j60Eth::receivePacket() +{ + uint8_t rxstat; + uint16_t len; + // check if a packet has been received and buffered + //if( !(readReg(EIR) & EIR_PKTIF) ){ + // The above does not work. See Rev. B4 Silicon Errata point 6. + if (readReg(EPKTCNT) != 0) { + uint16_t readPtr = nextPacketPtr + + 6 > RXEND_INIT ? nextPacketPtr + + 6 - + RXEND_INIT + + RXSTART_INIT : nextPacketPtr + + 6; + // Set the read pointer to the start of the received packet + writeRegPair(ERDPTL, nextPacketPtr); + + // read the next packet pointer + nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0); + nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; + + // read the packet length (see datasheet page 43) + len = readOp(ENC28J60_READ_BUF_MEM, 0); + len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; + len -= 4; //remove the CRC count + // 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 + printf + ( + "receivePacket [%d-%d], next: %d, stat: %d, count: %d -> ", + readPtr, + (readPtr + len) % (RXEND_INIT + 1), + nextPacketPtr, + rxstat, + readReg(EPKTCNT) + ); + (rxstat & 0x80) != 0 ? printf("OK") : printf("failed"); + printf("\r\n"); +#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): + // The ERXFCON.CRCEN is set by default. Normally we should not + // need to check this. + if ((rxstat & 0x80) != 0) { + receivePkt.begin = readPtr; + receivePkt.size = len; + return UIP_RECEIVEBUFFERHANDLE; + } + + // Move the RX read pointer to the start of the next received packet + // This frees the memory we just read out + setERXRDPT(); + } + + return(NOBLOCK); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::setERXRDPT() +{ + writeRegPair(ERXRDPTL, nextPacketPtr == RXSTART_INIT ? RXEND_INIT : nextPacketPtr - 1); +} + +/** + * @brief + * @note + * @param + * @retval + */ +memaddress Enc28j60Eth::blockSize(memhandle handle) +{ + return handle == NOBLOCK ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::sendPacket(memhandle handle) +{ + memblock* packet = &blocks[handle]; + uint16_t start = packet->begin - 1; + uint16_t end = start + packet->size; + + // backup data at control-byte position + uint8_t data = readByte(start); + // write control-byte (if not 0 anyway) + if (data) + writeByte(start, 0); + +#ifdef ENC28J60DEBUG + printf("sendPacket(%d) [%d-%d]: ", handle, start, end); + for (uint16_t i = start; i <= end; i++) { + printf("%d ", readByte(i)); + } + + printf("\r\n"); +#endif + // TX start + + writeRegPair(ETXSTL, start); + + // Set the TXND pointer to correspond to the packet size given + writeRegPair(ETXNDL, end); + + // send the contents of the transmit buffer onto the network + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); + + // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12. + if ((readReg(EIR) & EIR_TXERIF)) { + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS); + } + + //restore data on control-byte position + if (data) + writeByte(start, data); +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint16_t Enc28j60Eth::setReadPtr(memhandle handle, memaddress position, uint16_t len) +{ + memblock* packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle]; + memaddress start = handle == UIP_RECEIVEBUFFERHANDLE && + packet->begin + + position > RXEND_INIT ? packet->begin + + position - + RXEND_INIT + + RXSTART_INIT : packet->begin + + position; + + writeRegPair(ERDPTL, start); + + if (len > packet->size - position) + len = packet->size - position; + return len; +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint16_t Enc28j60Eth::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) +{ + len = setReadPtr(handle, position, len); + readBuffer(len, buffer); + return len; +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint16_t Enc28j60Eth::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) +{ + memblock* packet = &blocks[handle]; + uint16_t start = packet->begin + position; + + writeRegPair(EWRPTL, start); + + if (len > packet->size - position) + len = packet->size - position; + writeBuffer(len, buffer); + return len; +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint8_t Enc28j60Eth::readByte(uint16_t addr) +{ + uint8_t result; + + writeRegPair(ERDPTL, addr); + + _cs = 0; + + // issue read command + _spi.write(ENC28J60_READ_BUF_MEM); + + // read data + result = _spi.write(0x00); + _cs = 1; + return(result); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::writeByte(uint16_t addr, uint8_t data) +{ + writeRegPair(EWRPTL, addr); + + _cs = 0; + + // issue write command + _spi.write(ENC28J60_WRITE_BUF_MEM); + + // write data + _spi.write(data); + _cs = 1; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::copyPacket +( + memhandle dest_pkt, + memaddress dest_pos, + memhandle src_pkt, + memaddress src_pos, + uint16_t len +) +{ + memblock* dest = &blocks[dest_pkt]; + memblock* src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt]; + memaddress start = src_pkt == UIP_RECEIVEBUFFERHANDLE && + src->begin + + src_pos > RXEND_INIT ? src->begin + + src_pos - + RXEND_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(); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::freePacket() +{ + setERXRDPT(); +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint8_t Enc28j60Eth::readOp(uint8_t op, uint8_t address) +{ + uint8_t result; + + _cs = 0; + + // issue read command + _spi.write(op | (address & ADDR_MASK)); + + // read data + result = _spi.write(0x00); + + // do dummy read if needed (for mac and mii, see datasheet page 29) + if (address & 0x80) + result = _spi.write(0x00); + + // release CS + _cs = 1; + return(result); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::writeOp(uint8_t op, uint8_t address, uint8_t data) +{ + _cs = 0; + + // issue write command + _spi.write(op | (address & ADDR_MASK)); + + // write data + _spi.write(data); + _cs = 1; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::readBuffer(uint16_t len, uint8_t* data) +{ + _cs = 0; + + // issue read command + _spi.write(ENC28J60_READ_BUF_MEM); + while (len) { + len--; + + // read data + *data = _spi.write(0x00); + data++; + } + + *data = '\0'; + _cs = 1; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::writeBuffer(uint16_t len, uint8_t* data) +{ + _cs = 0; + + // issue write command + _spi.write(ENC28J60_WRITE_BUF_MEM); + while (len) { + len--; + + // write data + _spi.write(*data); + data++; + } + + _cs = 1; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::setBank(uint8_t address) +{ + // set the bank (if needed) + if ((address & BANK_MASK) != bank) { + // set the bank + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1 | ECON1_BSEL0)); + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK) >> 5); + bank = (address & BANK_MASK); + } +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint8_t Enc28j60Eth::readReg(uint8_t address) +{ + // set the bank + setBank(address); + + // do the read + return readOp(ENC28J60_READ_CTRL_REG, address); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::writeReg(uint8_t address, uint8_t data) +{ + // set the bank + setBank(address); + + // do the write + writeOp(ENC28J60_WRITE_CTRL_REG, address, data); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::writeRegPair(uint8_t address, uint16_t data) +{ + // set the bank + setBank(address); + + // do the write + writeOp(ENC28J60_WRITE_CTRL_REG, address, (data & 0xFF)); + writeOp(ENC28J60_WRITE_CTRL_REG, address + 1, (data) >> 8); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::phyWrite(uint8_t address, uint16_t data) +{ + // set the PHY register address + writeReg(MIREGADR, address); + + // write the PHY data + writeRegPair(MIWRL, data); + + // wait until the PHY write completes + while (readReg(MISTAT) & MISTAT_BUSY) { + wait_us(15); + } +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint16_t Enc28j60Eth::phyRead(uint8_t address) +{ + writeReg(MIREGADR, address); + writeReg(MICMD, MICMD_MIIRD); + + // wait until the PHY read completes + while (readReg(MISTAT) & MISTAT_BUSY) { + wait_us(15); + } //and MIRDH + + writeReg(MICMD, 0); + return(readReg(MIRDL) | readReg(MIRDH) << 8); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::clkout(uint8_t clk) +{ + //setup clkout: 2 is 12.5MHz: + writeReg(ECOCON, clk & 0x7); +} + +// read the revision of the chip: +uint8_t Enc28j60Eth::getrev() +{ + return(readReg(EREVID)); +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint16_t Enc28j60Eth::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) +{ + uint8_t spdr; + uint16_t t; + uint16_t i; + + len = setReadPtr(handle, pos, len) - 1; + _cs = 0; + + // issue read command + spdr = _spi.write(ENC28J60_READ_BUF_MEM); + for (i = 0; i < len; i += 2) { + // read data + spdr = _spi.write(0x00); + t = spdr << 8; + spdr = _spi.write(0x00); + t += spdr; + sum += t; + if (sum < t) { + sum++; /* carry */ + } + } + + if (i == len) { + spdr = _spi.write(0x00); + t = (spdr << 8) + 0; + sum += t; + if (sum < t) { + sum++; /* carry */ + } + } + + _cs = 1; + + /* Return sum in host byte order. */ + return sum; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::powerOff() +{ + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN); + wait_ms(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS); + wait_ms(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28j60Eth::powerOn() +{ + writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV); + wait_ms(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); + wait_ms(50); +} + +/** + * @brief + * @note + * @param + * @retval + */ +bool Enc28j60Eth::linkStatus() +{ + return(phyRead(PHSTAT2) & 0x0400) > 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utility/Enc28j60Eth.h Fri Aug 30 08:11:40 2019 +0000 @@ -0,0 +1,82 @@ +/* + Enc28J60Network.h + UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. + + Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> + All rights reserved. + + based on enc28j60.c file from the AVRlib library by Pascal Stang. + For AVRlib See http://www.procyonengineering.com/ + + Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef ENC28J60PHY_H +#define ENC28J60PHY_H + +#include "mbed.h" +#include "MemPool.h" + +#define UIP_RECEIVEBUFFERHANDLE 0xff + +//#define ENC28J60DEBUG + +class Enc28j60Eth : public MemPool +{ +private: + SPI _spi; + DigitalOut _cs; + static uint16_t nextPacketPtr; + static uint8_t bank; + + static struct memblock receivePkt; + + uint16_t setReadPtr(memhandle handle, memaddress position, uint16_t len); + void setERXRDPT(); + void readBuffer(uint16_t len, uint8_t* data); + void writeBuffer(uint16_t len, uint8_t* data); + void setBank(uint8_t address); + uint8_t readReg(uint8_t address); + void writeReg(uint8_t address, uint8_t data); + void phyWrite(uint8_t address, uint16_t data); + uint16_t phyRead(uint8_t address); + void clkout(uint8_t clk); + + friend void enc28j60_mempool_block_move_callback(memaddress, memaddress, memaddress); +public: + Enc28j60Eth(PinName mosi, PinName miso, PinName sclk, PinName cs); + uint8_t getrev(); + void powerOn(); + void powerOff(); + bool linkStatus(); + + void init(uint8_t* macaddr); + memhandle receivePacket(); + void freePacket(); + memaddress blockSize(memhandle handle); + void sendPacket(memhandle handle); + uint16_t readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); + uint16_t writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); + void copyPacket(memhandle dest, memaddress dest_pos, memhandle src, memaddress src_pos, uint16_t len); + uint16_t chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len); + + uint8_t readOp(uint8_t op, uint8_t address); + uint8_t readByte(uint16_t addr); + void writeOp(uint8_t op, uint8_t address, uint8_t data); + void writeRegPair(uint8_t address, uint16_t data); + void writeByte(uint16_t addr, uint8_t data); +}; + +#endif
--- a/utility/Enc28j60Py.cpp Tue Aug 27 22:08:54 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,729 +0,0 @@ -/* - Enc28J60Network.cpp - UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. - - Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> - All rights reserved. - - based on enc28j60.c file from the AVRlib library by Pascal Stang. - For AVRlib See http://www.procyonengineering.com/ - - Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#include "Enc28j60Py.h" -#include "mbed.h" - -extern "C" -{ -#include "enc28j60.h" -#include "uip.h" -} - -// Static member initialization -uint16_t Enc28j60Phy::nextPacketPtr; -uint8_t Enc28j60Phy::bank = 0xff; -struct memblock Enc28j60Phy::receivePkt; - -/** - * @brief - * @note - * @param - * @retval - */ -Enc28j60Phy::Enc28j60Phy(PinName mosi, PinName miso, PinName sclk, PinName cs) : - MemPool(), - _spi(mosi, miso, sclk), - _cs(cs) -{ } - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::init(uint8_t* macaddr) -{ - MemPool::init(); // 1 byte in between RX_STOP_INIT and pool to allow prepending of controlbyte - // initialize SPI interface - _spi.format(8, 0); // 8-bit, mode 0 - _spi.frequency(10000000); // 10 Mbit/s - wait_ms(1000); // 1 second for stable state - // Release SPI - _cs = 1; - - // perform system reset - writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); - - // check CLKRDY bit to see if reset is complete - //while(!(readReg(ESTAT) & ESTAT_CLKRDY)); - // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait. - wait_ms(50); - - // do bank 0 stuff - // initialize receive buffer - // 16-bit transfers, must write low byte first - // set receive buffer start address - nextPacketPtr = RXSTART_INIT; - - // Rx start - writeRegPair(ERXSTL, RXSTART_INIT); - - // set receive pointer address - writeRegPair(ERXRDPTL, RXSTART_INIT); - - // RX end - writeRegPair(ERXNDL, RXSTOP_INIT); - - // TX start - //writeRegPair(ETXSTL, TXSTART_INIT); - // TX end - //writeRegPair(ETXNDL, TXSTOP_INIT); - // do bank 1 stuff, packet filter: - // For broadcast packets we allow only ARP packtets - // All other packets should be unicast only for our mac (MAADR) - // - // The pattern to match on is therefore - // Type ETH.DST - // ARP BROADCAST - // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9 - // in binary these poitions are:11 0000 0011 1111 - // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 - //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN! - writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN | ERXFCON_BCEN); - writeRegPair(EPMM0, 0x303f); - writeRegPair(EPMCSL, 0xf7f9); - - // - // - // do bank 2 stuff - // enable MAC receive - // and bring MAC out of reset (writes 0x00 to MACON2) - writeRegPair(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS); - - // enable automatic padding to 60bytes and CRC operations - writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN); - - // set inter-frame gap (non-back-to-back) - writeRegPair(MAIPGL, 0x0C12); - - // set inter-frame gap (back-to-back) - writeReg(MABBIPG, 0x12); - - // Set the maximum packet size which the controller will accept - // Do not send packets longer than MAX_FRAMELEN: - writeRegPair(MAMXFLL, MAX_FRAMELEN); - - // do bank 3 stuff - // write MAC address - // NOTE: MAC address in ENC28J60 is byte-backward - writeReg(MAADR5, macaddr[0]); - writeReg(MAADR4, macaddr[1]); - writeReg(MAADR3, macaddr[2]); - writeReg(MAADR2, macaddr[3]); - writeReg(MAADR1, macaddr[4]); - writeReg(MAADR0, macaddr[5]); - - // no loopback of transmitted frames - phyWrite(PHCON2, PHCON2_HDLDIS); - - // switch to bank 0 - setBank(ECON1); - - // enable interrutps - writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE); - - // enable packet reception - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); - - //Configure leds - phyWrite(PHLCON, 0x476); -} - -/** - * @brief - * @note - * @param - * @retval - */ -memhandle Enc28j60Phy::receivePacket() -{ - uint8_t rxstat; - uint16_t len; - // check if a packet has been received and buffered - //if( !(readReg(EIR) & EIR_PKTIF) ){ - // The above does not work. See Rev. B4 Silicon Errata point 6. - if (readReg(EPKTCNT) != 0) { - 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 - nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0); - nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; - - // read the packet length (see datasheet page 43) - len = readOp(ENC28J60_READ_BUF_MEM, 0); - len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; - len -= 4; //remove the CRC count - // 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 - printf - ( - "receivePacket [%d-%d], next: %d, stat: %d, count: %d -> ", - readPtr, - (readPtr + len) % (RXSTOP_INIT + 1), - nextPacketPtr, - rxstat, - readReg(EPKTCNT) - ); - (rxstat & 0x80) != 0 ? printf("OK") : printf("failed"); - printf("\r\n"); -#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): - // The ERXFCON.CRCEN is set by default. Normally we should not - // need to check this. - if ((rxstat & 0x80) != 0) { - receivePkt.begin = readPtr; - receivePkt.size = len; - return UIP_RECEIVEBUFFERHANDLE; - } - - // Move the RX read pointer to the start of the next received packet - // This frees the memory we just read out - setERXRDPT(); - } - - return(NOBLOCK); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::setERXRDPT() -{ - writeRegPair(ERXRDPTL, nextPacketPtr == RXSTART_INIT ? RXSTOP_INIT : nextPacketPtr - 1); -} - -/** - * @brief - * @note - * @param - * @retval - */ -memaddress Enc28j60Phy::blockSize(memhandle handle) -{ - return handle == NOBLOCK ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::sendPacket(memhandle handle) -{ - memblock* packet = &blocks[handle]; - uint16_t start = packet->begin - 1; - uint16_t end = start + packet->size; - - // backup data at control-byte position - uint8_t data = readByte(start); - // write control-byte (if not 0 anyway) - if (data) - writeByte(start, 0); - -#ifdef ENC28J60DEBUG - printf("sendPacket(%d) [%d-%d]: ", handle, start, end); - for (uint16_t i = start; i <= end; i++) { - printf("%d ", readByte(i)); - } - - printf("\r\n"); -#endif - // TX start - - writeRegPair(ETXSTL, start); - - // Set the TXND pointer to correspond to the packet size given - writeRegPair(ETXNDL, end); - - // send the contents of the transmit buffer onto the network - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); - - // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12. - if ((readReg(EIR) & EIR_TXERIF)) { - writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS); - } - - //restore data on control-byte position - if (data) - writeByte(start, data); -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint16_t Enc28j60Phy::setReadPtr(memhandle handle, memaddress position, uint16_t len) -{ - memblock* packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle]; - 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) - len = packet->size - position; - return len; -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint16_t Enc28j60Phy::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) -{ - len = setReadPtr(handle, position, len); - readBuffer(len, buffer); - return len; -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint16_t Enc28j60Phy::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) -{ - memblock* packet = &blocks[handle]; - uint16_t start = packet->begin + position; - - writeRegPair(EWRPTL, start); - - if (len > packet->size - position) - len = packet->size - position; - writeBuffer(len, buffer); - return len; -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint8_t Enc28j60Phy::readByte(uint16_t addr) -{ - uint8_t result; - - writeRegPair(ERDPTL, addr); - - _cs = 0; - - // issue read command - _spi.write(ENC28J60_READ_BUF_MEM); - - // read data - result = _spi.write(0x00); - _cs = 1; - return(result); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::writeByte(uint16_t addr, uint8_t data) -{ - writeRegPair(EWRPTL, addr); - - _cs = 0; - - // issue write command - _spi.write(ENC28J60_WRITE_BUF_MEM); - - // write data - _spi.write(data); - _cs = 1; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::copyPacket -( - memhandle dest_pkt, - memaddress dest_pos, - memhandle src_pkt, - memaddress src_pos, - uint16_t len -) -{ - memblock* dest = &blocks[dest_pkt]; - memblock* src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt]; - 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(); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::freePacket() -{ - setERXRDPT(); -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint8_t Enc28j60Phy::readOp(uint8_t op, uint8_t address) -{ - uint8_t result; - - _cs = 0; - - // issue read command - _spi.write(op | (address & ADDR_MASK)); - - // read data - result = _spi.write(0x00); - - // do dummy read if needed (for mac and mii, see datasheet page 29) - if (address & 0x80) - result = _spi.write(0x00); - - // release CS - _cs = 1; - return(result); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::writeOp(uint8_t op, uint8_t address, uint8_t data) -{ - _cs = 0; - - // issue write command - _spi.write(op | (address & ADDR_MASK)); - - // write data - _spi.write(data); - _cs = 1; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::readBuffer(uint16_t len, uint8_t* data) -{ - _cs = 0; - - // issue read command - _spi.write(ENC28J60_READ_BUF_MEM); - while (len) { - len--; - - // read data - *data = _spi.write(0x00); - data++; - } - - *data = '\0'; - _cs = 1; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::writeBuffer(uint16_t len, uint8_t* data) -{ - _cs = 0; - - // issue write command - _spi.write(ENC28J60_WRITE_BUF_MEM); - while (len) { - len--; - - // write data - _spi.write(*data); - data++; - } - - _cs = 1; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::setBank(uint8_t address) -{ - // set the bank (if needed) - if ((address & BANK_MASK) != bank) { - // set the bank - writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1 | ECON1_BSEL0)); - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK) >> 5); - bank = (address & BANK_MASK); - } -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint8_t Enc28j60Phy::readReg(uint8_t address) -{ - // set the bank - setBank(address); - - // do the read - return readOp(ENC28J60_READ_CTRL_REG, address); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::writeReg(uint8_t address, uint8_t data) -{ - // set the bank - setBank(address); - - // do the write - writeOp(ENC28J60_WRITE_CTRL_REG, address, data); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::writeRegPair(uint8_t address, uint16_t data) -{ - // set the bank - setBank(address); - - // do the write - writeOp(ENC28J60_WRITE_CTRL_REG, address, (data & 0xFF)); - writeOp(ENC28J60_WRITE_CTRL_REG, address + 1, (data) >> 8); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::phyWrite(uint8_t address, uint16_t data) -{ - // set the PHY register address - writeReg(MIREGADR, address); - - // write the PHY data - writeRegPair(MIWRL, data); - - // wait until the PHY write completes - while (readReg(MISTAT) & MISTAT_BUSY) { - wait_us(15); - } -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint16_t Enc28j60Phy::phyRead(uint8_t address) -{ - writeReg(MIREGADR, address); - writeReg(MICMD, MICMD_MIIRD); - - // wait until the PHY read completes - while (readReg(MISTAT) & MISTAT_BUSY) { - wait_us(15); - } //and MIRDH - - writeReg(MICMD, 0); - return(readReg(MIRDL) | readReg(MIRDH) << 8); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::clkout(uint8_t clk) -{ - //setup clkout: 2 is 12.5MHz: - writeReg(ECOCON, clk & 0x7); -} - -// read the revision of the chip: -uint8_t Enc28j60Phy::getrev() -{ - return(readReg(EREVID)); -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint16_t Enc28j60Phy::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) -{ - uint8_t spdr; - uint16_t t; - uint16_t i; - - len = setReadPtr(handle, pos, len) - 1; - _cs = 0; - - // issue read command - spdr = _spi.write(ENC28J60_READ_BUF_MEM); - for (i = 0; i < len; i += 2) { - // read data - spdr = _spi.write(0x00); - t = spdr << 8; - spdr = _spi.write(0x00); - t += spdr; - sum += t; - if (sum < t) { - sum++; /* carry */ - } - } - - if (i == len) { - spdr = _spi.write(0x00); - t = (spdr << 8) + 0; - sum += t; - if (sum < t) { - sum++; /* carry */ - } - } - - _cs = 1; - - /* Return sum in host byte order. */ - return sum; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::powerOff() -{ - writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN); - wait_ms(50); - writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS); - wait_ms(50); - writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28j60Phy::powerOn() -{ - writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV); - wait_ms(50); - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); - wait_ms(50); -} - -/** - * @brief - * @note - * @param - * @retval - */ -bool Enc28j60Phy::linkStatus() -{ - return(phyRead(PHSTAT2) & 0x0400) > 0; -}
--- a/utility/Enc28j60Py.h Tue Aug 27 22:08:54 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - Enc28J60Network.h - UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. - - Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> - All rights reserved. - - based on enc28j60.c file from the AVRlib library by Pascal Stang. - For AVRlib See http://www.procyonengineering.com/ - - Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#ifndef ENC28J60PHY_H -#define ENC28J60PHY_H - -#include "mbed.h" -#include "MemPool.h" - -#define UIP_RECEIVEBUFFERHANDLE 0xff - -//#define ENC28J60DEBUG - -class Enc28j60Phy : public MemPool -{ -private: - SPI _spi; - DigitalOut _cs; - static uint16_t nextPacketPtr; - static uint8_t bank; - - static struct memblock receivePkt; - - uint16_t setReadPtr(memhandle handle, memaddress position, uint16_t len); - void setERXRDPT(); - void readBuffer(uint16_t len, uint8_t* data); - void writeBuffer(uint16_t len, uint8_t* data); - void setBank(uint8_t address); - uint8_t readReg(uint8_t address); - void writeReg(uint8_t address, uint8_t data); - void phyWrite(uint8_t address, uint16_t data); - uint16_t phyRead(uint8_t address); - void clkout(uint8_t clk); - - friend void enc28j60_mempool_block_move_callback(memaddress, memaddress, memaddress); -public: - Enc28j60Phy(PinName mosi, PinName miso, PinName sclk, PinName cs); - uint8_t getrev(); - void powerOn(); - void powerOff(); - bool linkStatus(); - - void init(uint8_t* macaddr); - memhandle receivePacket(); - void freePacket(); - memaddress blockSize(memhandle handle); - void sendPacket(memhandle handle); - uint16_t readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); - uint16_t writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); - void copyPacket(memhandle dest, memaddress dest_pos, memhandle src, memaddress src_pos, uint16_t len); - uint16_t chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len); - - uint8_t readOp(uint8_t op, uint8_t address); - uint8_t readByte(uint16_t addr); - void writeOp(uint8_t op, uint8_t address, uint8_t data); - void writeRegPair(uint8_t address, uint16_t data); - void writeByte(uint16_t addr, uint8_t data); -}; - -#endif
--- a/utility/enc28j60.h Tue Aug 27 22:08:54 2019 +0000 +++ b/utility/enc28j60.h Fri Aug 30 08:11:40 2019 +0000 @@ -222,35 +222,36 @@ #define PHCON2_HDLDIS 0x0100 // ENC28J60 Packet Control Byte Bit Definitions -#define PKTCTRL_PHUGEEN 0x08 -#define PKTCTRL_PPADEN 0x04 -#define PKTCTRL_PCRCEN 0x02 -#define PKTCTRL_POVERRIDE 0x01 +#define PKTCTRL_PHUGEEN 0x08 +#define PKTCTRL_PPADEN 0x04 +#define PKTCTRL_PCRCEN 0x02 +#define PKTCTRL_POVERRIDE 0x01 // SPI operation codes -#define ENC28J60_READ_CTRL_REG 0x00 -#define ENC28J60_READ_BUF_MEM 0x3A -#define ENC28J60_WRITE_CTRL_REG 0x40 -#define ENC28J60_WRITE_BUF_MEM 0x7A -#define ENC28J60_BIT_FIELD_SET 0x80 -#define ENC28J60_BIT_FIELD_CLR 0xA0 -#define ENC28J60_SOFT_RESET 0xFF +#define ENC28J60_READ_CTRL_REG 0x00 +#define ENC28J60_READ_BUF_MEM 0x3A +#define ENC28J60_WRITE_CTRL_REG 0x40 +#define ENC28J60_WRITE_BUF_MEM 0x7A +#define ENC28J60_BIT_FIELD_SET 0x80 +#define ENC28J60_BIT_FIELD_CLR 0xA0 +#define ENC28J60_SOFT_RESET 0xFF -// The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata -// buffer boundaries applied to internal 8K ram -// the entire available packet buffer space is allocated +// The RXSTART_INIT should be zero. See Silicon Errata: +// Sometimes, when ERXST or ERXND is written to, the exact value, 0000h, is stored in the Internal +// Receive Write Pointer instead of the ERXST address. +// Work around +// Use the lower segment of the buffer memory for the receive buffer, starting at address 0000h. +// For example, use the range (0000h to n) for the receive buffer, and ((n + 1) to 8191) for the transmit buffer. +#define RXSTART_INIT 0x0 +// Receive buffer end. Make sure this is an odd value (See Rev. B1,B4,B5,B7 Silicon Errata 'Memory (Ethernet Buffer)') +#define RXEND_INIT 0x11CB // = (3 * 1518) + 1 +// Start TX buffer RXEND_INIT + 1 +#define TXSTART_INIT RXEND_INIT + 1 +// end TX buffer at end of mem +#define TXEND_INIT 0x1FFF // -// start with recbuf at 0/ -#define RXSTART_INIT 0x0 -// receive buffer end. make sure this is an odd value (See Rev. B1,B4,B5,B7 Silicon Errata 'Memory (Ethernet Buffer)') -#define RXSTOP_INIT (0x1FFF-0x1800) -// start TX buffer RXSTOP_INIT+1 -#define TXSTART_INIT (0x1FFF-0x1800+1) -// stp TX buffer at end of mem -#define TXSTOP_INIT 0x1FFF -// -// max frame length which the conroller will accept: -#define MAX_FRAMELEN 1500 // (note: maximum ethernet frame length would be 1518) +// Max frame length which the conroller will accept: +#define MAX_FRAMELEN 1518 // (note: maximum ethernet frame length is 1518) #endif
--- a/utility/mempool_conf.h Tue Aug 27 22:08:54 2019 +0000 +++ b/utility/mempool_conf.h Fri Aug 30 08:11:40 2019 +0000 @@ -17,13 +17,13 @@ #define NUM_TCP_MEMBLOCKS 0 #endif #if UIP_UDP and UIP_UDP_CONNS -#define NUM_UDP_MEMBLOCKS 3 * UIP_UDP_CONNS +#define NUM_UDP_MEMBLOCKS (3 * UIP_UDP_CONNS) #else #define NUM_UDP_MEMBLOCKS 0 #endif #define MEMPOOL_NUM_MEMBLOCKS (NUM_TCP_MEMBLOCKS + NUM_UDP_MEMBLOCKS) -#define MEMPOOL_STARTADDRESS TXSTART_INIT + 1 -#define MEMPOOL_SIZE TXSTOP_INIT - TXSTART_INIT +#define MEMPOOL_STARTADDRESS (TXSTART_INIT + 1) +#define MEMPOOL_SIZE (TXEND_INIT - TXSTART_INIT) void enc28j60_mempool_block_move_callback(memaddress, memaddress, memaddress);
--- a/utility/uip.h Tue Aug 27 22:08:54 2019 +0000 +++ b/utility/uip.h Fri Aug 30 08:11:40 2019 +0000 @@ -58,7 +58,7 @@ */ typedef u16_t uip_ip4addr_t[2]; -typedef u16_t uip_ip6addr_t[8]; +typedef u16_t uip_ip6addr_t[8]; #if UIP_CONF_IPV6 typedef uip_ip6addr_t uip_ipaddr_t; #else /* UIP_CONF_IPV6 */