From fa66984cec630d0e2d51b1f063b841e6644746ef Mon Sep 17 00:00:00 2001 From: sstaub Date: Wed, 27 Jun 2018 06:56:16 +0200 Subject: [PATCH 01/58] MAC support (#11) Mac address support Signed-off-by: sstaub --- AUTHORS | 1 + README.md | 25 ++++++ .../AdvancedChatServer/AdvancedChatServer.ino | 10 +-- .../BarometricPressureWebServer.ino | 9 +-- examples/ChatServer/ChatServer.ino | 10 +-- .../DhcpAddressPrinter/DhcpAddressPrinter.ino | 8 +- examples/DhcpChatServer/DhcpChatServer.ino | 12 ++- examples/TelnetClient/TelnetClient.ino | 10 +-- .../UDPSendReceiveString.ino | 10 +-- examples/UdpNtpClient/UdpNtpClient.ino | 10 +-- examples/WebClient/WebClient.ino | 9 +-- .../WebClientRepeating/WebClientRepeating.ino | 13 ++- examples/WebServer/WebServer.ino | 10 +-- keywords.txt | 1 + src/STM32Ethernet.cpp | 79 ++++++++++++++++++- src/STM32Ethernet.h | 17 +++- 16 files changed, 166 insertions(+), 68 deletions(-) diff --git a/AUTHORS b/AUTHORS index e9f8f6b..8f8eb4f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -31,6 +31,7 @@ Paul Stoffregen https://github.com/PaulStoffregen per1234 https://github.com/per1234 Richard Sim Scott Fitzgerald https://github.com/shfitz +Stefan Staub https://github.com/sstaub STMicroelectronics https://github.com/stm32duino Thibaut Viard https://github.com/aethaniel Tom Igoe https://github.com/tigoe diff --git a/README.md b/README.md index 60c268d..9106f6e 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,31 @@ This library provides a default user defined options file named `lwipopts_defaul User can provide his own defined options at sketch level by adding his configuration in a file named `STM32lwipopts.h`. + +## New alternative init procedure **!!!** + +There are alternative inits of the Ethernetinterface with following orders: + + Ethernet.begin(); + Ethernet.begin(ip); + Ethernet.begin(ip, subnet); + Ethernet.begin(ip, subnet, gateway); + Ethernet.begin(ip, subnet, gateway, dns); + +This is more logical. A MAC address is no more needed and will retrieved internally by the mbed MAC address! + +You can get the MAC address with following function, this must done after Ethernet.Begin() + + uint8_t *mac; + Ethernet.begin(); + mac = Ethernet.macAddress(); + +You can also set a new user based MAC address, this must done before Ethernet.begin() + + uint8_t newMAC[] = {0x00, 0x80, 0xE1, 0x01, 0x01, 0x01}; + Ethernet.macAddress(newMAC); + Ethernet.begin(); + ## Note `EthernetClass::maintain()` in no more required to renew IP address from DHCP.
diff --git a/examples/AdvancedChatServer/AdvancedChatServer.ino b/examples/AdvancedChatServer/AdvancedChatServer.ino index e3719a6..1680233 100644 --- a/examples/AdvancedChatServer/AdvancedChatServer.ino +++ b/examples/AdvancedChatServer/AdvancedChatServer.ino @@ -17,18 +17,18 @@ by Norbert Truchsess modified 23 Jun 2017 by Wi6Labs + modified 1 Jun 2018 + by sstaub */ #include #include -// Enter a MAC address and IP address for your controller below. +// Enter an IP address for your controller below. // The IP address will be dependent on your local network. // gateway and subnet are optional: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED -}; + IPAddress ip(192, 168, 1, 177); IPAddress myDns(192, 168, 1, 1); IPAddress gateway(192, 168, 1, 1); @@ -42,7 +42,7 @@ EthernetClient clients[4]; void setup() { // initialize the Ethernet device - Ethernet.begin(mac, ip, myDns, gateway, subnet); + Ethernet.begin(ip, subnet, gateway, myDns); // start listening for clients server.begin(); // Open serial communications and wait for port to open: diff --git a/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino b/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino index 32516cd..96dbcbc 100644 --- a/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino +++ b/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino @@ -20,6 +20,8 @@ by Tom Igoe modified 23 Jun 2017 by Wi6Labs + modified 1 Jun 2018 + by sstaub */ #include @@ -28,11 +30,6 @@ #include -// assign a MAC address for the Ethernet controller. -// fill in your address here: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED -}; // assign an IP address for the controller: IPAddress ip(192, 168, 1, 20); @@ -62,7 +59,7 @@ void setup() { SPI.begin(); // start the Ethernet connection and the server: - Ethernet.begin(mac, ip); + Ethernet.begin(ip); server.begin(); // initalize the data ready and chip select pins: diff --git a/examples/ChatServer/ChatServer.ino b/examples/ChatServer/ChatServer.ino index 8ee5126..5c3aa3d 100644 --- a/examples/ChatServer/ChatServer.ino +++ b/examples/ChatServer/ChatServer.ino @@ -14,17 +14,17 @@ by Tom Igoe modified 23 Jun 2017 by Wi6Labs + modified 1 Jun 2018 + by sstaub */ #include #include -// Enter a MAC address and IP address for your controller below. +// Enter an IP address for your controller below. // The IP address will be dependent on your local network. // gateway and subnet are optional: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED -}; + IPAddress ip(192, 168, 1, 177); IPAddress myDns(192,168,1, 1); IPAddress gateway(192, 168, 1, 1); @@ -37,7 +37,7 @@ boolean alreadyConnected = false; // whether or not the client was connected pre void setup() { // initialize the ethernet device - Ethernet.begin(mac, ip, myDns, gateway, subnet); + Ethernet.begin(ip, subnet, gateway, myDns); // start listening for clients server.begin(); // Open serial communications and wait for port to open: diff --git a/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino b/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino index d17d97c..7f5c702 100644 --- a/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino +++ b/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino @@ -14,15 +14,13 @@ by Arturo Guadalupi modified 23 Jun 2017 by Wi6Labs + modified 1 Jun 2018 + by sstaub */ #include #include -// Enter a MAC address for your controller below. -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED -}; // Initialize the Ethernet client library // with the IP address and port of the server @@ -38,7 +36,7 @@ void setup() { } // start the Ethernet connection: - if (Ethernet.begin(mac) == 0) { + if (Ethernet.begin() == 0) { Serial.println("Failed to configure Ethernet using DHCP"); // no point in carrying on, so do nothing forevermore: for (;;) diff --git a/examples/DhcpChatServer/DhcpChatServer.ino b/examples/DhcpChatServer/DhcpChatServer.ino index 842bf4d..50ac63f 100644 --- a/examples/DhcpChatServer/DhcpChatServer.ino +++ b/examples/DhcpChatServer/DhcpChatServer.ino @@ -18,18 +18,16 @@ Based on ChatServer example by David A. Mellis modified 23 Jun 2017 by Wi6Labs - + modified 1 Jun 2018 + by sstaub */ #include #include -// Enter a MAC address and IP address for your controller below. +// Enter an IP address for your controller below. // The IP address will be dependent on your local network. // gateway and subnet are optional: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED -}; IPAddress ip(192, 168, 1, 177); IPAddress myDns(192,168,1, 1); IPAddress gateway(192, 168, 1, 1); @@ -50,10 +48,10 @@ void setup() { // start the Ethernet connection: Serial.println("Trying to get an IP address using DHCP"); - if (Ethernet.begin(mac) == 0) { + if (Ethernet.begin() == 0) { Serial.println("Failed to configure Ethernet using DHCP"); // initialize the Ethernet device not using DHCP: - Ethernet.begin(mac, ip, myDns, gateway, subnet); + Ethernet.begin(ip, subnet, gateway, myDns); } // print your local IP address: Serial.print("My IP address: "); diff --git a/examples/TelnetClient/TelnetClient.ino b/examples/TelnetClient/TelnetClient.ino index e503504..48fafe8 100644 --- a/examples/TelnetClient/TelnetClient.ino +++ b/examples/TelnetClient/TelnetClient.ino @@ -17,17 +17,15 @@ by Tom Igoe modified 23 Jun 2017 by Wi6Labs - + modified 1 Jun 2018 + by sstaub */ #include #include -// Enter a MAC address and IP address for your controller below. +// Enter an IP address for your controller below. // The IP address will be dependent on your local network: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED -}; IPAddress ip(192, 168, 1, 177); // Enter the IP address of the server you're connecting to: @@ -41,7 +39,7 @@ EthernetClient client; void setup() { // start the Ethernet connection: - Ethernet.begin(mac, ip); + Ethernet.begin(ip); // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { diff --git a/examples/UDPSendReceiveString/UDPSendReceiveString.ino b/examples/UDPSendReceiveString/UDPSendReceiveString.ino index 00e040b..7665fd9 100644 --- a/examples/UDPSendReceiveString/UDPSendReceiveString.ino +++ b/examples/UDPSendReceiveString/UDPSendReceiveString.ino @@ -10,7 +10,8 @@ by Michael Margolis modified 23 Jun 2017 by Wi6Labs - + modified 1 Jun 2018 + by sstaub This code is in the public domain. */ @@ -19,11 +20,8 @@ #include // UDP library from: bjoern@cs.stanford.edu 12/30/2008 -// Enter a MAC address and IP address for your controller below. +// Enter an IP address for your controller below. // The IP address will be dependent on your local network: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED -}; IPAddress ip(192, 168, 1, 177); unsigned int localPort = 8888; // local port to listen on @@ -37,7 +35,7 @@ EthernetUDP Udp; void setup() { // start the Ethernet and UDP: - Ethernet.begin(mac, ip); + Ethernet.begin(ip); Udp.begin(localPort); Serial.begin(9600); diff --git a/examples/UdpNtpClient/UdpNtpClient.ino b/examples/UdpNtpClient/UdpNtpClient.ino index 716c365..3ce84de 100644 --- a/examples/UdpNtpClient/UdpNtpClient.ino +++ b/examples/UdpNtpClient/UdpNtpClient.ino @@ -15,7 +15,8 @@ by Arturo Guadalupi modified 23 Jun 2017 by Wi6Labs - + modified 1 Jun 2018 + by sstaub This code is in the public domain. */ @@ -24,11 +25,6 @@ #include #include -// Enter a MAC address for your controller below. -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED -}; - unsigned int localPort = 8888; // local port to listen for UDP packets char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server @@ -49,7 +45,7 @@ void setup() { // start Ethernet and UDP - if (Ethernet.begin(mac) == 0) { + if (Ethernet.begin() == 0) { Serial.println("Failed to configure Ethernet using DHCP"); // no point in carrying on, so do nothing forevermore: for (;;) diff --git a/examples/WebClient/WebClient.ino b/examples/WebClient/WebClient.ino index 18be08d..35c9d7b 100644 --- a/examples/WebClient/WebClient.ino +++ b/examples/WebClient/WebClient.ino @@ -12,14 +12,13 @@ by Tom Igoe, based on work by Adrian McEwen modified 23 Jun 2017 by Wi6Labs - + modified 1 Jun 2018 + by sstaub */ #include #include -// Enter a MAC address for your controller below. -byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // if you don't want to use DNS (and reduce your sketch size) // use the numeric IP instead of the name for the server: //IPAddress server(74,125,232,128); // numeric IP for Google (no DNS) @@ -41,10 +40,10 @@ void setup() { } // start the Ethernet connection: - if (Ethernet.begin(mac) == 0) { + if (Ethernet.begin() == 0) { Serial.println("Failed to configure Ethernet using DHCP"); // try to congifure using IP address instead of DHCP: - Ethernet.begin(mac, ip); + Ethernet.begin(ip); } // give the Ethernet shield a second to initialize: delay(1000); diff --git a/examples/WebClientRepeating/WebClientRepeating.ino b/examples/WebClientRepeating/WebClientRepeating.ino index 61919d7..38482de 100644 --- a/examples/WebClientRepeating/WebClientRepeating.ino +++ b/examples/WebClientRepeating/WebClientRepeating.ino @@ -15,7 +15,8 @@ by Federico Vanzati modified 23 Jun 2017 by Wi6Labs - + modified 1 Jun 2018 + by sstaub http://www.arduino.cc/en/Tutorial/WebClientRepeating This code is in the public domain. @@ -24,15 +25,11 @@ #include #include -// assign a MAC address for the ethernet controller. -// fill in your address here: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED -}; // fill in an available IP address on your network here, // for manual configuration: IPAddress ip(192, 168, 1, 177); - +IPAddress gateway(192, 168, 1, 1); +IPAddress subnet(255, 255, 0, 0); // fill in your Domain Name Server address here: IPAddress myDns(1, 1, 1, 1); @@ -56,7 +53,7 @@ void setup() { // give the ethernet module time to boot up: delay(1000); // start the Ethernet connection using a fixed IP address and DNS server: - Ethernet.begin(mac, ip, myDns); + Ethernet.begin(ip, subnet, gateway, myDns); // print the Ethernet board/shield's IP address: Serial.print("My IP address: "); Serial.println(Ethernet.localIP()); diff --git a/examples/WebServer/WebServer.ino b/examples/WebServer/WebServer.ino index 3e6b318..e47900c 100644 --- a/examples/WebServer/WebServer.ino +++ b/examples/WebServer/WebServer.ino @@ -15,17 +15,15 @@ by Arturo Guadalupi modified 23 Jun 2017 by Wi6Labs - + modified 1 Jun 2018 + by sstaub */ #include #include -// Enter a MAC address and IP address for your controller below. +// Enter an IP address for your controller below. // The IP address will be dependent on your local network: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED -}; IPAddress ip(192, 168, 1, 177); // Initialize the Ethernet server library @@ -42,7 +40,7 @@ void setup() { // start the Ethernet connection and the server: - Ethernet.begin(mac, ip); + Ethernet.begin(ip); server.begin(); Serial.print("server is at "); Serial.println(Ethernet.localIP()); diff --git a/keywords.txt b/keywords.txt index 1f19b2a..78f7315 100644 --- a/keywords.txt +++ b/keywords.txt @@ -32,6 +32,7 @@ remoteIP KEYWORD2 remotePort KEYWORD2 getSocketNumber KEYWORD2 localIP KEYWORD2 +macAddress KEYWORD2 maintain KEYWORD2 ####################################### diff --git a/src/STM32Ethernet.cpp b/src/STM32Ethernet.cpp index 0f806c5..e406df5 100644 --- a/src/STM32Ethernet.cpp +++ b/src/STM32Ethernet.cpp @@ -1,6 +1,55 @@ #include "STM32Ethernet.h" #include "Dhcp.h" +int EthernetClass::begin(unsigned long timeout, unsigned long responseTimeout) +{ + static DhcpClass s_dhcp; + _dhcp = &s_dhcp; + stm32_eth_init(macAddressDefault(), NULL, NULL, NULL); + + // Now try to get our config info from a DHCP server + int ret = _dhcp->beginWithDHCP(mac_address, timeout, responseTimeout); + if(ret == 1) + { + _dnsServerAddress = _dhcp->getDnsServerIp(); + } + + return ret; +} + +void EthernetClass::begin(IPAddress local_ip) +{ + IPAddress subnet(255, 255, 255, 0); + begin(local_ip, subnet); +} + +void EthernetClass::begin(IPAddress local_ip, IPAddress subnet) +{ + // Assume the gateway will be the machine on the same network as the local IP + // but with last octet being '1' + IPAddress gateway = local_ip; + gateway[3] = 1; + begin(local_ip, subnet, gateway); +} + +void EthernetClass::begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway) +{ + // Assume the DNS server will be the machine on the same network as the local IP + // but with last octet being '1' + IPAddress dns_server = local_ip; + dns_server[3] = 1; + begin(local_ip, subnet, gateway, dns_server); +} + +void EthernetClass::begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server) +{ + stm32_eth_init(macAddressDefault(), local_ip.raw_address(), gateway.raw_address(), subnet.raw_address()); + /* If there is a local DHCP informs it of our manual IP configuration to + prevent IP conflict */ + stm32_DHCP_manual_config(); + _dnsServerAddress = dns_server; +} + int EthernetClass::begin(uint8_t *mac_address, unsigned long timeout, unsigned long responseTimeout) { static DhcpClass s_dhcp; @@ -14,7 +63,7 @@ int EthernetClass::begin(uint8_t *mac_address, unsigned long timeout, unsigned l { _dnsServerAddress = _dhcp->getDnsServerIp(); } - + macAddress(mac_address); return ret; } @@ -49,6 +98,7 @@ void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server prevent IP conflict */ stm32_DHCP_manual_config(); _dnsServerAddress = dns_server; + macAddress(mac); } int EthernetClass::maintain(){ @@ -82,6 +132,33 @@ void EthernetClass::schedule(void) stm32_eth_scheduler(); } +uint8_t * EthernetClass::macAddressDefault(void) +{ + if ((mac_address[0] + mac_address[1] + mac_address[2] + mac_address[3] + mac_address[4] + mac_address[5]) == 0) { + uint32_t baseUID = *(uint32_t *)UID_BASE; + mac_address[0] = 0x00; + mac_address[1] = 0x80; + mac_address[2] = 0xE1; + mac_address[3] = (baseUID & 0x00FF0000) >> 16; + mac_address[4] = (baseUID & 0x0000FF00) >> 8; + mac_address[5] = (baseUID & 0x000000FF); + } + return mac_address; +} + +void EthernetClass::macAddress(uint8_t *mac) { + mac_address[0] = mac[0]; + mac_address[1] = mac[1]; + mac_address[2] = mac[2]; + mac_address[3] = mac[3]; + mac_address[4] = mac[4]; + mac_address[5] = mac[5]; +} + +uint8_t * EthernetClass::macAddress(void) { + return mac_address; +} + IPAddress EthernetClass::localIP() { return IPAddress(stm32_eth_get_ipaddr()); diff --git a/src/STM32Ethernet.h b/src/STM32Ethernet.h index 78afbb7..c392275 100644 --- a/src/STM32Ethernet.h +++ b/src/STM32Ethernet.h @@ -11,7 +11,18 @@ class EthernetClass { private: IPAddress _dnsServerAddress; DhcpClass* _dhcp; + uint8_t mac_address[6]; + uint8_t * macAddressDefault(void); + public: + // Initialise the Ethernet with the internal provided MAC address and gain the rest of the + // configuration through DHCP. + // Returns 0 if the DHCP configuration failed, and 1 if it succeeded + int begin(unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + void begin(IPAddress local_ip); + void begin(IPAddress local_ip, IPAddress subnet); + void begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway); + void begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server); // Initialise the Ethernet shield to use the provided MAC address and gain the rest of the // configuration through DHCP. // Returns 0 if the DHCP configuration failed, and 1 if it succeeded @@ -20,9 +31,13 @@ class EthernetClass { void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server); void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway); void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); + + int maintain(); void schedule(void); - + + void macAddress(uint8_t *mac); + uint8_t * macAddress(void); IPAddress localIP(); IPAddress subnetMask(); IPAddress gatewayIP(); From d1bb81057cc2e55ab963aa84fc5513be4446eb47 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Wed, 31 Oct 2018 10:19:34 +0100 Subject: [PATCH 02/58] Update library.properties --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 0cbb04a..69e5105 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino STM32Ethernet -version=1.0.3 +version=1.0.4 author=Various maintainer=STMicroelectronics sentence=Enables network connection (local and Internet) using the STM32 Board. From a1db02b751b67c2751cf4fa46d9d45aa92cfeabd Mon Sep 17 00:00:00 2001 From: "Frederic.Pillon" Date: Mon, 26 Nov 2018 09:52:44 +0100 Subject: [PATCH 03/58] Use bool instead of boolean https://github.com/arduino/Arduino/issues/4673 Signed-off-by: Frederic.Pillon --- examples/AdvancedChatServer/AdvancedChatServer.ino | 2 +- .../BarometricPressureWebServer/BarometricPressureWebServer.ino | 2 +- examples/ChatServer/ChatServer.ino | 2 +- examples/DhcpChatServer/DhcpChatServer.ino | 2 +- examples/WebServer/WebServer.ino | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/AdvancedChatServer/AdvancedChatServer.ino b/examples/AdvancedChatServer/AdvancedChatServer.ino index 1680233..cdb236a 100644 --- a/examples/AdvancedChatServer/AdvancedChatServer.ino +++ b/examples/AdvancedChatServer/AdvancedChatServer.ino @@ -63,7 +63,7 @@ void loop() { // when the client sends the first byte, say hello: if (client) { - boolean newClient = true; + bool newClient = true; for (byte i = 0; i < 4; i++) { //check whether this client refers to the same socket as one of the existing instances: if (clients[i] == client) { diff --git a/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino b/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino index 96dbcbc..666f527 100644 --- a/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino +++ b/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino @@ -128,7 +128,7 @@ void listenForEthernetClients() { if (client) { Serial.println("Got a client"); // an http request ends with a blank line - boolean currentLineIsBlank = true; + bool currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); diff --git a/examples/ChatServer/ChatServer.ino b/examples/ChatServer/ChatServer.ino index 5c3aa3d..cffbabf 100644 --- a/examples/ChatServer/ChatServer.ino +++ b/examples/ChatServer/ChatServer.ino @@ -33,7 +33,7 @@ IPAddress subnet(255, 255, 0, 0); // telnet defaults to port 23 EthernetServer server(23); -boolean alreadyConnected = false; // whether or not the client was connected previously +bool alreadyConnected = false; // whether or not the client was connected previously void setup() { // initialize the ethernet device diff --git a/examples/DhcpChatServer/DhcpChatServer.ino b/examples/DhcpChatServer/DhcpChatServer.ino index 50ac63f..d2561fb 100644 --- a/examples/DhcpChatServer/DhcpChatServer.ino +++ b/examples/DhcpChatServer/DhcpChatServer.ino @@ -35,7 +35,7 @@ IPAddress subnet(255, 255, 0, 0); // telnet defaults to port 23 EthernetServer server(23); -boolean gotAMessage = false; // whether or not you got a message from the client yet +bool gotAMessage = false; // whether or not you got a message from the client yet void setup() { // Open serial communications and wait for port to open: diff --git a/examples/WebServer/WebServer.ino b/examples/WebServer/WebServer.ino index e47900c..9030ee4 100644 --- a/examples/WebServer/WebServer.ino +++ b/examples/WebServer/WebServer.ino @@ -53,7 +53,7 @@ void loop() { if (client) { Serial.println("new client"); // an http request ends with a blank line - boolean currentLineIsBlank = true; + bool currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); From be067d9c0a30ed211b92bae9ebbf46b0bbf48454 Mon Sep 17 00:00:00 2001 From: Philippe Coval Date: Fri, 4 Jan 2019 11:14:14 +0100 Subject: [PATCH 04/58] client: Fix bool operator on init and ongoing use When iterating we make sure client's socket is not closing since _tcp_client remains after close. This was tested on nuleo-f767zi using project webthing-arduino Change-Id: Ie465fe59009c33957dad97f1c70b4dc3af3b2ebe Forwarded: https://github.com/stm32duino/STM32Ethernet/pull/17 Signed-off-by: Philippe Coval --- src/EthernetClient.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/EthernetClient.cpp b/src/EthernetClient.cpp index f02c486..349ffb6 100644 --- a/src/EthernetClient.cpp +++ b/src/EthernetClient.cpp @@ -9,12 +9,14 @@ extern "C" { #include "EthernetServer.h" #include "Dns.h" -EthernetClient::EthernetClient() { +EthernetClient::EthernetClient() + :_tcp_client(NULL) { } /* Deprecated constructor. Keeps compatibility with W5100 architecture sketches but sock is ignored. */ -EthernetClient::EthernetClient(uint8_t sock) { +EthernetClient::EthernetClient(uint8_t sock) + :_tcp_client(NULL) { UNUSED(sock); } @@ -181,7 +183,7 @@ uint8_t EthernetClient::status() { // EthernetServer::available() as the condition in an if-statement. EthernetClient::operator bool() { - return _tcp_client != NULL; + return (_tcp_client && (_tcp_client->state != TCP_CLOSING)); } bool EthernetClient::operator==(const EthernetClient& rhs) { From a443221fb53d196cdd399d5193ec6f05177aa18a Mon Sep 17 00:00:00 2001 From: Philippe Coval Date: Fri, 4 Jan 2019 13:59:40 +0100 Subject: [PATCH 05/58] server: Initialize class member on dynamic alloc Also replace default constructor to use port 80 by default. I noticed that server worked on global instance. but not if used in class (allocated with new). This change makes both use cases working. Forwarded: https://github.com/stm32duino/STM32Ethernet/pull/17 Relate-to: https://github.com/rzr/webthing-iotjs/wiki/MCU Change-Id: I2e21e34a43f3cadb7981f2e359a5960735daa5d3 Signed-off-by: Philippe Coval --- src/EthernetServer.cpp | 2 ++ src/EthernetServer.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/EthernetServer.cpp b/src/EthernetServer.cpp index f5353d8..18ff147 100644 --- a/src/EthernetServer.cpp +++ b/src/EthernetServer.cpp @@ -9,6 +9,8 @@ extern "C" { EthernetServer::EthernetServer(uint16_t port) { _port = port; + _tcp_client[MAX_CLIENT] = {}; + _tcp_server = {}; } void EthernetServer::begin() diff --git a/src/EthernetServer.h b/src/EthernetServer.h index 317bf41..fb42c43 100644 --- a/src/EthernetServer.h +++ b/src/EthernetServer.h @@ -14,7 +14,7 @@ public Server { void accept(void); public: - EthernetServer(uint16_t); + EthernetServer(uint16_t port = 80); EthernetClient available(); virtual void begin(); virtual size_t write(uint8_t); From 13a0adf9ece8038458c94d560af2708cc5346cff Mon Sep 17 00:00:00 2001 From: Stefan Staub Date: Sat, 22 Dec 2018 18:48:47 +0100 Subject: [PATCH 06/58] Create library.json --- library.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100755 library.json diff --git a/library.json b/library.json new file mode 100755 index 0000000..f1a6d3d --- /dev/null +++ b/library.json @@ -0,0 +1,13 @@ +{ + "name": "STM32Ethernet", + "keywords": "Ethernet", + "description": "Arduino library to support Ethernet for STM32 based board.", + "repository": + { + "type": "git", + "url": "https://github.com/stm32duino/STM32Ethernet" + }, + "version": "1.0.4", + "frameworks": "arduino", + "platforms": "ststm32" +} From ad95c45afa8e9c727c70826d39d93d81d8c62b33 Mon Sep 17 00:00:00 2001 From: Stefan Staub Date: Fri, 10 May 2019 16:52:40 +0200 Subject: [PATCH 07/58] Update library.json --- library.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library.json b/library.json index f1a6d3d..b93a2b7 100755 --- a/library.json +++ b/library.json @@ -7,7 +7,10 @@ "type": "git", "url": "https://github.com/stm32duino/STM32Ethernet" }, - "version": "1.0.4", + "version": "1.0.5", "frameworks": "arduino", - "platforms": "ststm32" + "platforms": "ststm32", + "build": { + "libArchive": false + } } From 72c849f248985a676267686ffa719dfecd0a7532 Mon Sep 17 00:00:00 2001 From: "Frederic.Pillon" Date: Fri, 10 May 2019 16:40:39 +0200 Subject: [PATCH 08/58] Remove useless variant.h include variant.h is now included thanks stm32_def.h See https://github.com/stm32duino/Arduino_Core_STM32/pull/518 Signed-off-by: Frederic.Pillon --- src/utility/ethernetif.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utility/ethernetif.c b/src/utility/ethernetif.c index eeb966c..3658064 100644 --- a/src/utility/ethernetif.c +++ b/src/utility/ethernetif.c @@ -52,7 +52,9 @@ #include #include "PeripheralPins.h" #include "stm32_eth.h" +#if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01050000) #include "variant.h" +#endif #ifdef __cplusplus extern "C" { From 71208860cf0ba177a64190fbbde34f0205902e4e Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Fri, 26 Jul 2019 15:38:50 +0200 Subject: [PATCH 09/58] Update STM32duino_STM32Ethernet library to use HardwareTimer library --- src/utility/{stm32_eth.c => stm32_eth.cpp} | 24 ++++++++++------------ 1 file changed, 11 insertions(+), 13 deletions(-) rename src/utility/{stm32_eth.c => stm32_eth.cpp} (98%) diff --git a/src/utility/stm32_eth.c b/src/utility/stm32_eth.cpp similarity index 98% rename from src/utility/stm32_eth.c rename to src/utility/stm32_eth.cpp index 4365b17..c64725d 100644 --- a/src/utility/stm32_eth.c +++ b/src/utility/stm32_eth.cpp @@ -1,6 +1,6 @@ /** ****************************************************************************** - * @file stm32_eth.c + * @file stm32_eth.cpp * @author WI6LABS * @version V1.0.0 * @date 24-May-2017 @@ -96,15 +96,12 @@ static uint8_t DHCP_Started_by_user = 0; /* Ethernet link status periodic timer */ static uint32_t gEhtLinkTickStart = 0; -/* Handler for stimer */ -static stimer_t TimHandle; - /*************************** Function prototype *******************************/ static void Netif_Config(void); static err_t tcp_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err); static err_t tcp_sent_callback(void *arg, struct tcp_pcb *tpcb, u16_t len); static void tcp_err_callback(void *arg, err_t err); -static void scheduler_callback(stimer_t *htim); +static void scheduler_callback(HardwareTimer *HT); static void TIM_scheduler_Config(void); /** @@ -139,12 +136,12 @@ static void Netif_Config(void) /** * @brief Scheduler callback. Call by a timer interrupt. -* @param htim: pointer to stimer_t +* @param htim: pointer to HardwareTimer * @retval None */ -static void scheduler_callback(stimer_t *htim) +static void scheduler_callback(HardwareTimer *HT) { - UNUSED(htim); + UNUSED(HT); stm32_eth_scheduler(); } @@ -156,13 +153,14 @@ static void scheduler_callback(stimer_t *htim) */ static void TIM_scheduler_Config(void) { - /* Set TIMx instance. */ - TimHandle.timer = DEFAULT_ETHERNET_TIMER; + /* Configure HardwareTimer */ + HardwareTimer *EthTim = new HardwareTimer(DEFAULT_ETHERNET_TIMER); + EthTim->setMode(1, TIMER_OUTPUT_COMPARE); /* Timer set to 1ms */ - TimerHandleInit(&TimHandle, (uint16_t)(1000 - 1), ((uint32_t)(getTimerClkFreq(DEFAULT_ETHERNET_TIMER) / (1000000)) - 1)); - - attachIntHandle(&TimHandle, scheduler_callback); + EthTim->setOverflow(1000, MICROSEC_FORMAT); + EthTim->attachInterrupt(scheduler_callback); + EthTim->resume(); } void stm32_eth_init(const uint8_t *mac, const uint8_t *ip, const uint8_t *gw, const uint8_t *netmask) From 568478e0f4ddc5622c7123a6761eb8193433c440 Mon Sep 17 00:00:00 2001 From: "Frederic.Pillon" Date: Wed, 21 Aug 2019 16:02:58 +0200 Subject: [PATCH 10/58] Ensure backward compatibility depending of the STM32 Core Version Signed-off-by: Frederic.Pillon --- src/utility/stm32_eth.cpp | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index c64725d..2f4db14 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -96,12 +96,16 @@ static uint8_t DHCP_Started_by_user = 0; /* Ethernet link status periodic timer */ static uint32_t gEhtLinkTickStart = 0; +#if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100) +/* Handler for stimer */ +static stimer_t TimHandle; +#endif + /*************************** Function prototype *******************************/ static void Netif_Config(void); static err_t tcp_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err); static err_t tcp_sent_callback(void *arg, struct tcp_pcb *tpcb, u16_t len); static void tcp_err_callback(void *arg, err_t err); -static void scheduler_callback(HardwareTimer *HT); static void TIM_scheduler_Config(void); /** @@ -136,15 +140,35 @@ static void Netif_Config(void) /** * @brief Scheduler callback. Call by a timer interrupt. -* @param htim: pointer to HardwareTimer +* @param htim: pointer to stimer_t or Hardware Timer * @retval None */ -static void scheduler_callback(HardwareTimer *HT) +#if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100) +static void scheduler_callback(stimer_t *htim) +#else +static void scheduler_callback(HardwareTimer *htim) +#endif { - UNUSED(HT); + UNUSED(htim); stm32_eth_scheduler(); } +#if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100) +/** +* @brief Enable the timer used to call ethernet scheduler function at regular +* interval. +* @param None +* @retval None +*/ +static void TIM_scheduler_Config(void) +{ + /* Set TIMx instance. */ + TimHandle.timer = DEFAULT_ETHERNET_TIMER; + /* Timer set to 1ms */ + TimerHandleInit(&TimHandle, (uint16_t)(1000 - 1), ((uint32_t)(getTimerClkFreq(DEFAULT_ETHERNET_TIMER) / (1000000)) - 1)); + attachIntHandle(&TimHandle, scheduler_callback); +} +#else /** * @brief Enable the timer used to call ethernet scheduler function at regular * interval. @@ -162,6 +186,7 @@ static void TIM_scheduler_Config(void) EthTim->attachInterrupt(scheduler_callback); EthTim->resume(); } +#endif void stm32_eth_init(const uint8_t *mac, const uint8_t *ip, const uint8_t *gw, const uint8_t *netmask) { From 3ebfc7be9946b8cdfb9d0b3b6ce13e99c276aa77 Mon Sep 17 00:00:00 2001 From: "Frederic.Pillon" Date: Thu, 22 Aug 2019 10:13:03 +0200 Subject: [PATCH 11/58] Allow to add extra options to the default one by adding a 'lwipopts_extra.h' Signed-off-by: Frederic.Pillon --- README.md | 4 ++- src/lwipopts.h | 3 ++ src/lwipopts_default.h | 62 ++++++++++++++++++------------------------ 3 files changed, 33 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 9106f6e..78e5755 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,9 @@ The LwIP has several user defined options, which is specified from within the `l This library provides a default user defined options file named `lwipopts_default.h`. -User can provide his own defined options at sketch level by adding his configuration in a file named `STM32lwipopts.h`. +User can provide his own defined options at sketch level by adding his configuration in a file named `STM32lwipopts.h` or +extend the default one by adding some extra configuration in a file named `lwipopts_extra.h`. + ## New alternative init procedure **!!!** diff --git a/src/lwipopts.h b/src/lwipopts.h index 56f805b..e3fb5f3 100644 --- a/src/lwipopts.h +++ b/src/lwipopts.h @@ -11,6 +11,9 @@ #if __has_include("STM32lwipopts.h") #include "STM32lwipopts.h" #else +#if __has_include("lwipopts_extra.h") +#include "lwipopts_extra.h" +#endif #include "lwipopts_default.h" #endif diff --git a/src/lwipopts_default.h b/src/lwipopts_default.h index 7a988f5..0a03e31 100644 --- a/src/lwipopts_default.h +++ b/src/lwipopts_default.h @@ -9,36 +9,10 @@ *

© Copyright (c) 2017 STMicroelectronics International N.V. * All rights reserved.

* - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: - * - * 1. Redistribution of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. - * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 * ****************************************************************************** */ @@ -58,6 +32,8 @@ */ #define SYS_LIGHTWEIGHT_PROT 0 +#define LWIP_NOASSERT + /* ---------- Memory options ---------- */ /* MEM_ALIGNMENT: should be set to the alignment of the CPU for which lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2 @@ -100,9 +76,13 @@ a lot of data that needs to be copied, this should be set high. */ /* ---------- TCP options ---------- */ #define LWIP_TCP 1 #define TCP_TTL 255 +#define LWIP_SO_RCVTIMEO 1 +#define LWIP_SO_RCVRCVTIMEO_NONSTANDARD 1 /* Pass an integer number of ms instead of a timeval struct. */ +#define LWIP_SO_SNDTIMEO 1 +#define LWIP_SO_SNDRCVTIMEO_NONSTANDARD 1 /* Pass an integer number of ms instead of a timeval struct. */ /* Controls if TCP should queue segments that arrive out of - order. Define to 0 if your device is low on memory. */ + order. Define to 0 if your device is low on memory and you are not scared by TCP congestion and latencies. */ #define TCP_QUEUE_OOSEQ 0 /* TCP Maximum segment size. */ @@ -117,19 +97,25 @@ a lot of data that needs to be copied, this should be set high. */ #define TCP_SND_QUEUELEN (2* TCP_SND_BUF/TCP_MSS) /* TCP receive window. */ -#define TCP_WND (2*TCP_MSS) +#define TCP_WND (3*TCP_MSS) + +#define LWIP_TCP_KEEPALIVE 1 /* Keep the TCP link active. Important for MQTT/TLS */ +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 /* Prevent the same port to be used after reset. + Otherwise, the remote host may be confused if the port was not explicitly closed before the reset. */ /* ---------- ICMP options ---------- */ #define LWIP_ICMP 1 +#define LWIP_RAW 1 /* PING changed to 1 */ +#define DEFAULT_RAW_RECVMBOX_SIZE 3 /* for ICMP PING */ /* ---------- DHCP options ---------- */ +/* Define LWIP_DHCP to 1 if you want DHCP configuration of + interfaces. DHCP is not implemented in lwIP 0.5.1, however, so + turning this on does currently not work. */ #define LWIP_DHCP 1 -/* ---------- DNS options ---------- */ -#define LWIP_DNS 1 - /* ---------- UDP options ---------- */ #define LWIP_UDP 1 @@ -138,12 +124,17 @@ a lot of data that needs to be copied, this should be set high. */ /* ---------- Statistics options ---------- */ #define LWIP_STATS 0 +#define LWIP_PROVIDE_ERRNO /* ---------- link callback options ---------- */ /* LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface * whenever the link changes (i.e., link down) */ +// need for building net_ip.c +#define LWIP_NETIF_HOSTNAME 1 +#define LWIP_NETIF_STATUS_CALLBACK 1 #define LWIP_NETIF_LINK_CALLBACK 1 +#define LWIP_DHCP_CHECK_LINK_UP 1 /* -------------------------------------- @@ -211,6 +202,7 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) */ #define LWIP_SOCKET 0 +#define LWIP_DNS 1 /* ------------------------------------ From 75fefe628c4d438463cc05373774f6d29d27f7f2 Mon Sep 17 00:00:00 2001 From: gdsports Date: Wed, 16 Oct 2019 14:27:13 -0700 Subject: [PATCH 12/58] Add EthernetClient functions: localPort, remoteIP, remotePort SSLClient needs these functions --- src/EthernetClient.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/EthernetClient.h b/src/EthernetClient.h index 1cf73d8..6734b6d 100644 --- a/src/EthernetClient.h +++ b/src/EthernetClient.h @@ -31,6 +31,9 @@ class EthernetClient : public Client { virtual bool operator==(const EthernetClient&); virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); }; uint8_t getSocketNumber(); + virtual uint16_t localPort() { return (_tcp_client->pcb->local_port); }; + virtual IPAddress remoteIP() { return (IPAddress(_tcp_client->pcb->remote_ip.addr)); }; + virtual uint16_t remotePort() { return (_tcp_client->pcb->remote_port); }; friend class EthernetServer; From cfe4f6496d7e5deb974498d0d6c4011819d0574c Mon Sep 17 00:00:00 2001 From: gdsports Date: Mon, 21 Oct 2019 15:31:59 -0700 Subject: [PATCH 13/58] Allocate the TCP client when needed. This patch allows the WebClientRepeating example to work. --- src/EthernetClient.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/EthernetClient.cpp b/src/EthernetClient.cpp index 349ffb6..f6978fb 100644 --- a/src/EthernetClient.cpp +++ b/src/EthernetClient.cpp @@ -40,16 +40,13 @@ int EthernetClient::connect(const char* host, uint16_t port) { } int EthernetClient::connect(IPAddress ip, uint16_t port) { - /* Can't create twice the same client */ - if(_tcp_client != NULL) { - return 0; - } - - /* Allocates memory for client */ - _tcp_client = (struct tcp_struct *)mem_malloc(sizeof(struct tcp_struct)); - if(_tcp_client == NULL) { - return 0; + /* Allocates memory for client */ + _tcp_client = (struct tcp_struct *)mem_malloc(sizeof(struct tcp_struct)); + + if(_tcp_client == NULL) { + return 0; + } } /* Creates a new TCP protocol control block */ From 193a5131ea79feb277712db40ffcd54a4fd6ab41 Mon Sep 17 00:00:00 2001 From: gdsports Date: Tue, 22 Oct 2019 16:11:02 -0700 Subject: [PATCH 14/58] Add Ethernet.linkStatus Also remove 2 printf debug. --- src/STM32Ethernet.cpp | 5 +++++ src/STM32Ethernet.h | 7 +++++++ src/utility/stm32_eth.cpp | 13 +++++++++---- src/utility/stm32_eth.h | 1 + 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/STM32Ethernet.cpp b/src/STM32Ethernet.cpp index e406df5..7a79a38 100644 --- a/src/STM32Ethernet.cpp +++ b/src/STM32Ethernet.cpp @@ -101,6 +101,11 @@ void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server macAddress(mac); } +EthernetLinkStatus EthernetClass::linkStatus() +{ + return (stm32_eth_link_up() ? LinkON : LinkOFF); +} + int EthernetClass::maintain(){ int rc = DHCP_CHECK_NONE; diff --git a/src/STM32Ethernet.h b/src/STM32Ethernet.h index c392275..5d814cd 100644 --- a/src/STM32Ethernet.h +++ b/src/STM32Ethernet.h @@ -7,6 +7,12 @@ #include "EthernetServer.h" #include "Dhcp.h" +enum EthernetLinkStatus { + Unknown, + LinkON, + LinkOFF +}; + class EthernetClass { private: IPAddress _dnsServerAddress; @@ -19,6 +25,7 @@ class EthernetClass { // configuration through DHCP. // Returns 0 if the DHCP configuration failed, and 1 if it succeeded int begin(unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + EthernetLinkStatus linkStatus(); void begin(IPAddress local_ip); void begin(IPAddress local_ip, IPAddress subnet); void begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway); diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index 2f4db14..08b0c3f 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -246,6 +246,15 @@ void stm32_eth_init(const uint8_t *mac, const uint8_t *ip, const uint8_t *gw, co stm32_eth_scheduler(); } +/** + * @brief Return Ethernet link status + * @param None + * @retval 1 for link up, 0 for link down + */ +uint8_t stm32_eth_link_up(void) { + return netif_is_link_up(&gnetif); +} + /** * @brief This function must be called in main loop in standalone mode. * @param None @@ -479,8 +488,6 @@ void ethernetif_notify_conn_changed(struct netif *netif) { if(netif_is_link_up(netif)) { - printf("Link up\n"); - /* Update DHCP state machine if DHCP used */ if(DHCP_Started_by_user == 1) { DHCP_state = DHCP_START; @@ -498,8 +505,6 @@ void ethernetif_notify_conn_changed(struct netif *netif) /* When the netif link is down this function must be called.*/ netif_set_down(netif); - - printf("Link down\n"); } } diff --git a/src/utility/stm32_eth.h b/src/utility/stm32_eth.h index bf1bb28..e537005 100644 --- a/src/utility/stm32_eth.h +++ b/src/utility/stm32_eth.h @@ -121,6 +121,7 @@ extern struct netif gnetif; /* Exported functions ------------------------------------------------------- */ void stm32_eth_init(const uint8_t *mac, const uint8_t *ip, const uint8_t *gw, const uint8_t *netmask); +uint8_t stm32_eth_link_up(void); void stm32_eth_scheduler(void); void User_notification(struct netif *netif); From 5f6c5b670bc42fc778603d8abd88573c33fa5341 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 25 Oct 2019 16:32:40 +0200 Subject: [PATCH 15/58] Update Ethernet.linkStatus to handle Unknown status Signed-off-by: Frederic Pillon --- src/STM32Ethernet.cpp | 2 +- src/utility/ethernetif.c | 11 +++++++++++ src/utility/ethernetif.h | 1 + src/utility/stm32_eth.cpp | 9 +++++++++ src/utility/stm32_eth.h | 1 + 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/STM32Ethernet.cpp b/src/STM32Ethernet.cpp index 7a79a38..1a72ed8 100644 --- a/src/STM32Ethernet.cpp +++ b/src/STM32Ethernet.cpp @@ -103,7 +103,7 @@ void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server EthernetLinkStatus EthernetClass::linkStatus() { - return (stm32_eth_link_up() ? LinkON : LinkOFF); + return (!stm32_eth_is_init()) ? Unknown : (stm32_eth_link_up() ? LinkON : LinkOFF); } int EthernetClass::maintain(){ diff --git a/src/utility/ethernetif.c b/src/utility/ethernetif.c index 3658064..a60a269 100644 --- a/src/utility/ethernetif.c +++ b/src/utility/ethernetif.c @@ -431,6 +431,17 @@ void ethernetif_input(struct netif *netif) } } +/** + * @brief Returns the current state + * + * @param None + * @return 0 not initialized else 1 + */ +uint8_t ethernetif_is_init(void) +{ + return (EthHandle.State != HAL_ETH_STATE_RESET); +} + /** * @brief Should be called at the beginning of the program to set up the * network interface. It calls the function low_level_init() to do the diff --git a/src/utility/ethernetif.h b/src/utility/ethernetif.h index e851c19..8f4c782 100644 --- a/src/utility/ethernetif.h +++ b/src/utility/ethernetif.h @@ -56,6 +56,7 @@ #endif /* Exported types ------------------------------------------------------------*/ +uint8_t ethernetif_is_init(void); err_t ethernetif_init(struct netif *netif); void ethernetif_input(struct netif *netif); void ethernetif_set_link(struct netif *netif); diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index 08b0c3f..f63a26d 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -246,6 +246,15 @@ void stm32_eth_init(const uint8_t *mac, const uint8_t *ip, const uint8_t *gw, co stm32_eth_scheduler(); } +/** + * @brief Return Ethernet init status + * @param None + * @retval 1 for initialized, 0 for not initialized + */ +uint8_t stm32_eth_is_init(void) { + return ethernetif_is_init(); +} + /** * @brief Return Ethernet link status * @param None diff --git a/src/utility/stm32_eth.h b/src/utility/stm32_eth.h index e537005..e90c7f8 100644 --- a/src/utility/stm32_eth.h +++ b/src/utility/stm32_eth.h @@ -121,6 +121,7 @@ extern struct netif gnetif; /* Exported functions ------------------------------------------------------- */ void stm32_eth_init(const uint8_t *mac, const uint8_t *ip, const uint8_t *gw, const uint8_t *netmask); +uint8_t stm32_eth_is_init(void); uint8_t stm32_eth_link_up(void); void stm32_eth_scheduler(void); From 07b379706b1b8442d4421792c183b8146c44a096 Mon Sep 17 00:00:00 2001 From: gdsports Date: Tue, 22 Oct 2019 21:11:28 -0700 Subject: [PATCH 16/58] Use UDP unconnected sockets UDP connected sockets are limited to commuinicating with one host and port. --- src/EthernetUdp.cpp | 13 ++++--------- src/EthernetUdp.h | 2 ++ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/EthernetUdp.cpp b/src/EthernetUdp.cpp index c5ae45c..057fa69 100644 --- a/src/EthernetUdp.cpp +++ b/src/EthernetUdp.cpp @@ -106,9 +106,8 @@ int EthernetUDP::beginPacket(IPAddress ip, uint16_t port) ip_addr_t ipaddr; - if(ERR_OK != udp_connect( _udp.pcb, u8_to_ip_addr(rawIPAddress(ip), &ipaddr), port)) { - return 0; - } + _sendtoIP = ip; + _sendtoPort = port; udp_recv(_udp.pcb, &udp_receive_callback, &_udp); stm32_eth_scheduler(); @@ -122,12 +121,8 @@ int EthernetUDP::endPacket() return 0; } - // A remote IP & port must be connected to udp pcb. Call ::beginPacket before. - if((udp_flags(_udp.pcb) & UDP_FLAGS_CONNECTED) != UDP_FLAGS_CONNECTED) { - return 0; - } - - if(ERR_OK != udp_send(_udp.pcb, _data)) { + ip_addr_t ipaddr; + if(ERR_OK != udp_sendto(_udp.pcb, _data, u8_to_ip_addr(rawIPAddress(_sendtoIP), &ipaddr), _sendtoPort)) { _data = stm32_free_data(_data); return 0; } diff --git a/src/EthernetUdp.h b/src/EthernetUdp.h index 8d7d878..f7f22e3 100644 --- a/src/EthernetUdp.h +++ b/src/EthernetUdp.h @@ -50,6 +50,8 @@ class EthernetUDP : public UDP { uint16_t _port; // local port to listen on IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed + IPAddress _sendtoIP; // the remote IP address set by beginPacket + uint16_t _sendtoPort; // the remote port set by beginPacket struct pbuf *_data; //pbuf for data to send struct udp_struct _udp; //udp settings From b956c4b29cef0f96893fc2bb73d067c7d2c6aa51 Mon Sep 17 00:00:00 2001 From: straccio Date: Tue, 16 Jan 2018 17:44:02 +0100 Subject: [PATCH 17/58] Added multicast udp, added callback for interrupt data arrival Implemented begin multicast for receiving multicast udp. Added ability to add a callback from the interrupt when udp receive data (Usefull with FreeRTOS). ``` void EthernetUDP::onDataArrival( std::function onDataArrival_fn){ _udp.onDataArrival = onDataArrival_fn; } ``` --- src/EthernetUdp.cpp | 35 ++++++-- src/EthernetUdp.h | 5 +- src/utility/{ethernetif.c => ethernetif.cpp} | 87 +++++++++++++++++++- src/utility/ethernetif.h | 12 +-- src/utility/stm32_eth.cpp | 12 +-- src/utility/stm32_eth.h | 10 +-- 6 files changed, 130 insertions(+), 31 deletions(-) mode change 100644 => 100755 src/EthernetUdp.cpp rename src/utility/{ethernetif.c => ethernetif.cpp} (89%) mode change 100644 => 100755 src/utility/ethernetif.h diff --git a/src/EthernetUdp.cpp b/src/EthernetUdp.cpp old mode 100644 new mode 100755 index 057fa69..c4bfff7 --- a/src/EthernetUdp.cpp +++ b/src/EthernetUdp.cpp @@ -25,16 +25,23 @@ * * bjoern@cs.stanford.edu 12/30/2008 */ - #include "STM32Ethernet.h" #include "Udp.h" #include "Dns.h" +#include "lwip/igmp.h" +#include "lwip/ip_addr.h" + /* Constructor */ EthernetUDP::EthernetUDP() {} /* Start EthernetUDP socket, listening at local port PORT */ uint8_t EthernetUDP::begin(uint16_t port) { + return begin(Ethernet.localIP(), port); +} + +/* Start EthernetUDP socket, listening at local IP ip and port PORT */ +uint8_t EthernetUDP::begin(IPAddress ip, uint16_t port, bool multicast) { // Can create a single udp connection per socket if(_udp.pcb != NULL) { return 0; @@ -46,14 +53,25 @@ uint8_t EthernetUDP::begin(uint16_t port) { return 0; } - IPAddress ip = Ethernet.localIP(); ip_addr_t ipaddr; + err_t err; + u8_to_ip_addr(rawIPAddress(ip), &ipaddr); + if (multicast) { + err = udp_bind(_udp.pcb, IP_ADDR_ANY, port); + } else { + err = udp_bind(_udp.pcb, &ipaddr, port); + } - if(ERR_OK != udp_bind(_udp.pcb, u8_to_ip_addr(rawIPAddress(ip), &ipaddr), port)) { + if(ERR_OK != err) { stop(); return 0; } +#if LWIP_IGMP + if ((multicast) && (ERR_OK != igmp_joingroup(IP_ADDR_ANY, &ipaddr))) { + return 0; + } +#endif udp_recv(_udp.pcb, &udp_receive_callback, &_udp); _port = port; @@ -104,8 +122,6 @@ int EthernetUDP::beginPacket(IPAddress ip, uint16_t port) return 0; } - ip_addr_t ipaddr; - _sendtoIP = ip; _sendtoPort = port; @@ -245,6 +261,11 @@ void EthernetUDP::flush() /* Start EthernetUDP socket, listening at local port PORT */ uint8_t EthernetUDP::beginMulticast(IPAddress ip, uint16_t port) { - UNUSED(ip); - return begin(port); + return begin(ip, port, true); +} + +#if LWIP_UDP +void EthernetUDP::onDataArrival( std::function onDataArrival_fn){ + _udp.onDataArrival = onDataArrival_fn; } +#endif diff --git a/src/EthernetUdp.h b/src/EthernetUdp.h index f7f22e3..0a1d2f9 100644 --- a/src/EthernetUdp.h +++ b/src/EthernetUdp.h @@ -38,10 +38,9 @@ #define ethernetudp_h #include +#include -extern "C" { #include "utility/stm32_eth.h" -} #define UDP_TX_PACKET_MAX_SIZE 24 @@ -62,6 +61,7 @@ class EthernetUDP : public UDP { public: EthernetUDP(); // Constructor virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual uint8_t begin(IPAddress, uint16_t, bool multicast = false); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use virtual uint8_t beginMulticast(IPAddress, uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use virtual void stop(); // Finish with the UDP socket @@ -104,6 +104,7 @@ class EthernetUDP : public UDP { virtual IPAddress remoteIP() { return _remoteIP; }; // Return the port of the host who sent the current incoming packet virtual uint16_t remotePort() { return _remotePort; }; + virtual void onDataArrival( std::function onDataArrival_fn); }; #endif diff --git a/src/utility/ethernetif.c b/src/utility/ethernetif.cpp similarity index 89% rename from src/utility/ethernetif.c rename to src/utility/ethernetif.cpp index a60a269..6ad4407 100644 --- a/src/utility/ethernetif.c +++ b/src/utility/ethernetif.cpp @@ -51,6 +51,7 @@ #include "ethernetif.h" #include #include "PeripheralPins.h" +#include "lwip/igmp.h" #include "stm32_eth.h" #if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01050000) #include "variant.h" @@ -92,6 +93,11 @@ static ETH_HandleTypeDef EthHandle; static uint8_t macaddress[6]= { MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5 }; +#if LWIP_IGMP +uint32_t ETH_HashTableHigh=0x0; +uint32_t ETH_HashTableLow=0x0; +#endif + /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /******************************************************************************* @@ -205,7 +211,9 @@ static void low_level_init(struct netif *netif) /* Enable MAC and DMA transmission and reception */ HAL_ETH_Start(&EthHandle); - +#if LWIP_IGMP + netif_set_igmp_mac_filter(netif, igmp_mac_filter); +#endif /**** Configure PHY to generate an interrupt when Eth Link state changes ****/ /* Read Register Configuration */ HAL_ETH_ReadPHYRegister(&EthHandle, PHY_IMR, ®value); @@ -214,6 +222,10 @@ static void low_level_init(struct netif *netif) /* Enable Interrupt on change of link status */ HAL_ETH_WritePHYRegister(&EthHandle, PHY_IMR, regvalue ); +#if LWIP_IGMP + ETH_HashTableHigh=EthHandle.Instance->MACHTHR; + ETH_HashTableLow=EthHandle.Instance->MACHTLR; +#endif } /** @@ -510,6 +522,13 @@ void ethernetif_set_link(struct netif *netif) HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, ®value); if((regvalue & PHY_LINKED_STATUS) != (uint16_t)RESET) { +#if LWIP_IGMP + if (!(netif->flags & NETIF_FLAG_IGMP)) { + netif->flags |= NETIF_FLAG_IGMP; + igmp_init(); + igmp_start(netif); + } +#endif netif_set_link_up(netif); } } @@ -628,6 +647,72 @@ void ethernetif_set_mac_addr(const uint8_t *mac) { } } +#if LWIP_IGMP +err_t igmp_mac_filter( struct netif *netif, const ip4_addr_t *ip4_addr, netif_mac_filter_action action ) +{ + uint8_t mac[6]; + const uint8_t *p = (const uint8_t *)ip4_addr; + + mac[0] = 0x01; + mac[1] = 0x00; + mac[2] = 0x5E; + mac[3] = *(p+1) & 0x7F; + mac[4] = *(p+2); + mac[5] = *(p+3); + + register_multicast_address(mac); + + return 0; +} + +#ifndef HASH_BITS +#define HASH_BITS 6 /* #bits in hash */ +#endif + +uint32_t ethcrc(const uint8_t *data, size_t length) +{ + uint32_t crc = 0xffffffff; + size_t i; + int j; + + for (i = 0; i < length; i++) { + for (j = 0; j < 8; j++) { + if (((crc >> 31) ^ (data[i] >> j)) & 0x01) { + /* x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 */ + crc = (crc << 1) ^ 0x04C11DB7; + } else { + crc = crc << 1; + } + } + } + return ~crc; +} + +void register_multicast_address(const uint8_t *mac) +{ + uint32_t crc; + uint8_t hash; + + /* Calculate crc32 value of mac address */ + crc = ethcrc(mac, HASH_BITS); + + /* + * Only upper HASH_BITS are used + * which point to specific bit in the hash registers + */ + hash = (crc >> 26) & 0x3F; + + if (hash > 31) { + ETH_HashTableHigh |= 1 << (hash - 32); + EthHandle.Instance->MACHTHR = ETH_HashTableHigh; + } else { + ETH_HashTableLow |= 1 << hash; + EthHandle.Instance->MACHTLR =ETH_HashTableLow; + } +} +#endif /* LWIP_IGMP */ + + #ifdef ETH_INPUT_USE_IT /** * @brief Ethernet Rx Transfer completed callback diff --git a/src/utility/ethernetif.h b/src/utility/ethernetif.h old mode 100644 new mode 100755 index 8f4c782..b0976fb --- a/src/utility/ethernetif.h +++ b/src/utility/ethernetif.h @@ -47,14 +47,11 @@ #ifndef __ETHERNETIF_H__ #define __ETHERNETIF_H__ - -#include "lwip/err.h" -#include "lwip/netif.h" - #ifdef __cplusplus extern "C" { #endif - +#include "lwip/err.h" +#include "lwip/netif.h" /* Exported types ------------------------------------------------------------*/ uint8_t ethernetif_is_init(void); err_t ethernetif_init(struct netif *netif); @@ -65,6 +62,11 @@ void ethernetif_notify_conn_changed(struct netif *netif); void ethernetif_set_mac_addr(const uint8_t *mac); +#if LWIP_IGMP +err_t igmp_mac_filter( struct netif *netif, const ip4_addr_t *ip4_addr, netif_mac_filter_action action ); +void register_multicast_address(const uint8_t *mac); +#endif + #ifdef __cplusplus } #endif diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index f63a26d..c7210dd 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -47,10 +47,6 @@ #include "lwip/prot/dhcp.h" #include "lwip/dns.h" -#ifdef __cplusplus - extern "C" { -#endif - /* Check ethernet link status every seconds */ #define TIME_CHECK_ETH_LINK_STATE 500U @@ -798,6 +794,10 @@ void udp_receive_callback(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_copy(udp_arg->ip, *addr); udp_arg->port = port; + + if(udp_arg->onDataArrival != NULL){ + udp_arg->onDataArrival(); + } } else { pbuf_free(p); } @@ -1049,7 +1049,3 @@ void tcp_connection_close(struct tcp_pcb *tpcb, struct tcp_struct *tcp) } #endif /* LWIP_TCP */ - -#ifdef __cplusplus -} -#endif diff --git a/src/utility/stm32_eth.h b/src/utility/stm32_eth.h index e90c7f8..fd1cad6 100644 --- a/src/utility/stm32_eth.h +++ b/src/utility/stm32_eth.h @@ -38,10 +38,6 @@ #ifndef __STM32_ETH_H__ #define __STM32_ETH_H__ -#ifdef __cplusplus - extern "C" { -#endif - /* Includes ------------------------------------------------------------------*/ #include "stm32_def.h" #include "lwip/ip_addr.h" @@ -49,6 +45,7 @@ #include "lwip/udp.h" #include "lwip/tcp.h" #include "lwip/opt.h" +#include /* Exported types ------------------------------------------------------------*/ /* TCP connection state */ @@ -74,6 +71,7 @@ struct udp_struct { struct pbuf_data data; ip_addr_t ip; // the remote IP address from which the packet was received u16_t port; // the remote port from which the packet was received + std::function onDataArrival; }; /* TCP structure */ @@ -174,8 +172,4 @@ void tcp_connection_close(struct tcp_pcb *tpcb, struct tcp_struct *tcp); #error "LWIP_TCP must be enabled in lwipopts.h" #endif -#ifdef __cplusplus -} -#endif - #endif /* __STM32_ETH_H__ */ From adf5ac4c9c42f01acc46fe49be6e6511f1e5bce6 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Sun, 10 Nov 2019 07:19:18 +0100 Subject: [PATCH 18/58] Update library.properties Signed-off-by: Frederic Pillon --- library.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 69e5105..2ad82c6 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino STM32Ethernet -version=1.0.4 +version=1.0.5 author=Various maintainer=STMicroelectronics sentence=Enables network connection (local and Internet) using the STM32 Board. @@ -7,3 +7,4 @@ paragraph=With this library you can use the STM32 board to connect to Internet. category=Communication url=https://github.com/stm32duino/STM32Ethernet architectures=stm32 +depends=STM32duino LwIP \ No newline at end of file From 87a5de5262a77146c3d35908d4ff03af8877859a Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 2 Jan 2020 11:08:18 +0100 Subject: [PATCH 19/58] Use Arduino naming for MAC address API Rename macAddress() to MACAddress(). Fixes #35 Signed-off-by: Frederic Pillon --- README.md | 4 ++-- keywords.txt | 2 +- src/STM32Ethernet.cpp | 14 +++++++------- src/STM32Ethernet.h | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 78e5755..6e2262d 100644 --- a/README.md +++ b/README.md @@ -43,12 +43,12 @@ You can get the MAC address with following function, this must done after Ethern uint8_t *mac; Ethernet.begin(); - mac = Ethernet.macAddress(); + mac = Ethernet.MACAddress(); You can also set a new user based MAC address, this must done before Ethernet.begin() uint8_t newMAC[] = {0x00, 0x80, 0xE1, 0x01, 0x01, 0x01}; - Ethernet.macAddress(newMAC); + Ethernet.MACAddress(newMAC); Ethernet.begin(); ## Note diff --git a/keywords.txt b/keywords.txt index 78f7315..367603a 100644 --- a/keywords.txt +++ b/keywords.txt @@ -32,7 +32,7 @@ remoteIP KEYWORD2 remotePort KEYWORD2 getSocketNumber KEYWORD2 localIP KEYWORD2 -macAddress KEYWORD2 +MACAddress KEYWORD2 maintain KEYWORD2 ####################################### diff --git a/src/STM32Ethernet.cpp b/src/STM32Ethernet.cpp index 1a72ed8..1611815 100644 --- a/src/STM32Ethernet.cpp +++ b/src/STM32Ethernet.cpp @@ -5,7 +5,7 @@ int EthernetClass::begin(unsigned long timeout, unsigned long responseTimeout) { static DhcpClass s_dhcp; _dhcp = &s_dhcp; - stm32_eth_init(macAddressDefault(), NULL, NULL, NULL); + stm32_eth_init(MACAddressDefault(), NULL, NULL, NULL); // Now try to get our config info from a DHCP server int ret = _dhcp->beginWithDHCP(mac_address, timeout, responseTimeout); @@ -43,7 +43,7 @@ void EthernetClass::begin(IPAddress local_ip, IPAddress subnet, IPAddress gatewa void EthernetClass::begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server) { - stm32_eth_init(macAddressDefault(), local_ip.raw_address(), gateway.raw_address(), subnet.raw_address()); + stm32_eth_init(MACAddressDefault(), local_ip.raw_address(), gateway.raw_address(), subnet.raw_address()); /* If there is a local DHCP informs it of our manual IP configuration to prevent IP conflict */ stm32_DHCP_manual_config(); @@ -63,7 +63,7 @@ int EthernetClass::begin(uint8_t *mac_address, unsigned long timeout, unsigned l { _dnsServerAddress = _dhcp->getDnsServerIp(); } - macAddress(mac_address); + MACAddress(mac_address); return ret; } @@ -98,7 +98,7 @@ void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server prevent IP conflict */ stm32_DHCP_manual_config(); _dnsServerAddress = dns_server; - macAddress(mac); + MACAddress(mac); } EthernetLinkStatus EthernetClass::linkStatus() @@ -137,7 +137,7 @@ void EthernetClass::schedule(void) stm32_eth_scheduler(); } -uint8_t * EthernetClass::macAddressDefault(void) +uint8_t * EthernetClass::MACAddressDefault(void) { if ((mac_address[0] + mac_address[1] + mac_address[2] + mac_address[3] + mac_address[4] + mac_address[5]) == 0) { uint32_t baseUID = *(uint32_t *)UID_BASE; @@ -151,7 +151,7 @@ uint8_t * EthernetClass::macAddressDefault(void) return mac_address; } -void EthernetClass::macAddress(uint8_t *mac) { +void EthernetClass::MACAddress(uint8_t *mac) { mac_address[0] = mac[0]; mac_address[1] = mac[1]; mac_address[2] = mac[2]; @@ -160,7 +160,7 @@ void EthernetClass::macAddress(uint8_t *mac) { mac_address[5] = mac[5]; } -uint8_t * EthernetClass::macAddress(void) { +uint8_t * EthernetClass::MACAddress(void) { return mac_address; } diff --git a/src/STM32Ethernet.h b/src/STM32Ethernet.h index 5d814cd..f9b20eb 100644 --- a/src/STM32Ethernet.h +++ b/src/STM32Ethernet.h @@ -18,7 +18,7 @@ class EthernetClass { IPAddress _dnsServerAddress; DhcpClass* _dhcp; uint8_t mac_address[6]; - uint8_t * macAddressDefault(void); + uint8_t * MACAddressDefault(void); public: // Initialise the Ethernet with the internal provided MAC address and gain the rest of the @@ -43,8 +43,8 @@ class EthernetClass { int maintain(); void schedule(void); - void macAddress(uint8_t *mac); - uint8_t * macAddress(void); + void MACAddress(uint8_t *mac); + uint8_t * MACAddress(void); IPAddress localIP(); IPAddress subnetMask(); IPAddress gatewayIP(); From dc0113149b319f513a6c86e70fcf5048aa2722ce Mon Sep 17 00:00:00 2001 From: Erik tideman Date: Fri, 10 Jan 2020 12:37:35 +0100 Subject: [PATCH 20/58] Fix issue with EthernetClient::write and large packages Fixes #37 --- src/EthernetClient.cpp | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/EthernetClient.cpp b/src/EthernetClient.cpp index f6978fb..53c0505 100644 --- a/src/EthernetClient.cpp +++ b/src/EthernetClient.cpp @@ -96,16 +96,35 @@ size_t EthernetClient::write(const uint8_t *buf, size_t size) { return 0; } - if(ERR_OK != tcp_write(_tcp_client->pcb, buf, size, TCP_WRITE_FLAG_COPY)) { - return 0; - } + size_t max_send_size, bytes_to_send; + size_t bytes_sent = 0; + size_t bytes_left = size; + err_t res; + + do{ + max_send_size = tcp_sndbuf(_tcp_client->pcb); + bytes_to_send = bytes_left > max_send_size ? max_send_size : bytes_left; + + if(bytes_to_send > 0){ + res = tcp_write(_tcp_client->pcb, &buf[bytes_sent], bytes_to_send, TCP_WRITE_FLAG_COPY); + + if(res == ERR_OK){ + bytes_sent += bytes_to_send; + bytes_left = size - bytes_sent; + } + else if(res != ERR_MEM){ + // other error, cannot continue + return 0; + } + } - //Force to send data right now! - if(ERR_OK != tcp_output(_tcp_client->pcb)) { - return 0; - } + //Force to send data right now! + if(ERR_OK != tcp_output(_tcp_client->pcb)) { + return 0; + } + stm32_eth_scheduler(); - stm32_eth_scheduler(); + } while(bytes_sent != size); return size; } From ccd2b2e946e22ff08a64b88b55aa060f65aaea1d Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Mon, 24 Feb 2020 14:15:21 +0100 Subject: [PATCH 21/58] Unified library source formatting Apply Astyle Clean up trailing space Ensure all files have the same format (Unix) Signed-off-by: Frederic Pillon --- src/Dhcp.cpp | 259 +++---- src/Dhcp.h | 90 +-- src/Dns.cpp | 115 ++- src/Dns.h | 77 +- src/EthernetClient.cpp | 106 +-- src/EthernetClient.h | 76 +- src/EthernetServer.cpp | 26 +- src/EthernetServer.h | 28 +- src/EthernetUdp.cpp | 61 +- src/EthernetUdp.h | 113 +-- src/STM32Ethernet.cpp | 21 +- src/STM32Ethernet.h | 76 +- src/lwipopts.h | 42 +- src/lwipopts_default.h | 482 ++++++------ src/utility/ethernetif.cpp | 1458 ++++++++++++++++++------------------ src/utility/ethernetif.h | 148 ++-- src/utility/stm32_eth.cpp | 334 ++++----- src/utility/stm32_eth.h | 5 +- 18 files changed, 1754 insertions(+), 1763 deletions(-) mode change 100755 => 100644 src/EthernetUdp.cpp mode change 100755 => 100644 src/utility/ethernetif.h diff --git a/src/Dhcp.cpp b/src/Dhcp.cpp index ac75c71..1725e4f 100644 --- a/src/Dhcp.cpp +++ b/src/Dhcp.cpp @@ -1,129 +1,130 @@ -// DHCP Library v0.3 - April 25, 2009 -// Author: Jordan Terrell - blog.jordanterrell.com - -#include -#include -#include "Dhcp.h" -#include "Arduino.h" -#include "utility/stm32_eth.h" - -int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) -{ - UNUSED(responseTimeout); - _timeout = timeout; - _dhcp_lease_state = DHCP_CHECK_NONE; - - // zero out _dhcpMacAddr - memset(_dhcpMacAddr, 0, 6); - reset_DHCP_lease(); - - memcpy((void*)_dhcpMacAddr, (void*)mac, 6); - _dhcp_state = STATE_DHCP_START; - stm32_set_DHCP_state(_dhcp_state); - return request_DHCP_lease(); -} - -void DhcpClass::reset_DHCP_lease(){ - _dhcp_state = STATE_DHCP_RELEASE; - stm32_set_DHCP_state(_dhcp_state); - stm32_eth_scheduler(); - _dhcp_state = stm32_get_DHCP_state(); -} - -//return:0 on error, 1 if request is sent and response is received -int DhcpClass::request_DHCP_lease(){ - - int result = 0; - unsigned long startTime = millis(); - - while(_dhcp_state != STATE_DHCP_LEASED) - { - stm32_eth_scheduler(); - _dhcp_state = stm32_get_DHCP_state(); - - if(result != 1 && ((millis() - startTime) > _timeout)) { - reset_DHCP_lease(); - break; - } - } - - if(_dhcp_state == STATE_DHCP_LEASED) { - result = 1; - } - - return result; -} - -/* - returns: - 0/DHCP_CHECK_NONE: nothing happened - 1/DHCP_CHECK_RENEW_FAIL: renew failed - 2/DHCP_CHECK_RENEW_OK: renew success - 3/DHCP_CHECK_REBIND_FAIL: rebind fail - 4/DHCP_CHECK_REBIND_OK: rebind success -*/ -int DhcpClass::checkLease(){ - int rc = DHCP_CHECK_NONE; - - stm32_eth_scheduler(); - rc = stm32_get_DHCP_lease_state(); - - if(rc != _dhcp_lease_state) - { - switch(_dhcp_lease_state) { - case DHCP_CHECK_NONE: - _dhcp_lease_state = rc; - rc = DHCP_CHECK_NONE; - break; - - case DHCP_CHECK_RENEW_OK: - _dhcp_lease_state = rc; - if(rc == DHCP_CHECK_NONE) { - rc = DHCP_CHECK_RENEW_OK; - } else { - rc = DHCP_CHECK_RENEW_FAIL; - } - break; - - case DHCP_CHECK_REBIND_OK: - _dhcp_lease_state = rc; - if(rc == DHCP_CHECK_NONE) { - rc = DHCP_CHECK_REBIND_OK; - } else { - rc = DHCP_CHECK_REBIND_FAIL; - } - break; - - default: - _dhcp_lease_state = DHCP_CHECK_NONE; - break; - } - } - - return rc; -} - -IPAddress DhcpClass::getLocalIp() -{ - return IPAddress(stm32_eth_get_ipaddr()); -} - -IPAddress DhcpClass::getSubnetMask() -{ - return IPAddress(stm32_eth_get_netmaskaddr()); -} - -IPAddress DhcpClass::getGatewayIp() -{ - return IPAddress(stm32_eth_get_gwaddr()); -} - -IPAddress DhcpClass::getDhcpServerIp() -{ - return IPAddress(stm32_eth_get_dhcpaddr()); -} - -IPAddress DhcpClass::getDnsServerIp() -{ - return IPAddress(stm32_eth_get_dnsaddr()); -} +// DHCP Library v0.3 - April 25, 2009 +// Author: Jordan Terrell - blog.jordanterrell.com + +#include +#include +#include "Dhcp.h" +#include "Arduino.h" +#include "utility/stm32_eth.h" + +int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) +{ + UNUSED(responseTimeout); + _timeout = timeout; + _dhcp_lease_state = DHCP_CHECK_NONE; + + // zero out _dhcpMacAddr + memset(_dhcpMacAddr, 0, 6); + reset_DHCP_lease(); + + memcpy((void *)_dhcpMacAddr, (void *)mac, 6); + _dhcp_state = STATE_DHCP_START; + stm32_set_DHCP_state(_dhcp_state); + return request_DHCP_lease(); +} + +void DhcpClass::reset_DHCP_lease() +{ + _dhcp_state = STATE_DHCP_RELEASE; + stm32_set_DHCP_state(_dhcp_state); + stm32_eth_scheduler(); + _dhcp_state = stm32_get_DHCP_state(); +} + +//return:0 on error, 1 if request is sent and response is received +int DhcpClass::request_DHCP_lease() +{ + + int result = 0; + unsigned long startTime = millis(); + + while (_dhcp_state != STATE_DHCP_LEASED) { + stm32_eth_scheduler(); + _dhcp_state = stm32_get_DHCP_state(); + + if (result != 1 && ((millis() - startTime) > _timeout)) { + reset_DHCP_lease(); + break; + } + } + + if (_dhcp_state == STATE_DHCP_LEASED) { + result = 1; + } + + return result; +} + +/* + returns: + 0/DHCP_CHECK_NONE: nothing happened + 1/DHCP_CHECK_RENEW_FAIL: renew failed + 2/DHCP_CHECK_RENEW_OK: renew success + 3/DHCP_CHECK_REBIND_FAIL: rebind fail + 4/DHCP_CHECK_REBIND_OK: rebind success +*/ +int DhcpClass::checkLease() +{ + int rc = DHCP_CHECK_NONE; + + stm32_eth_scheduler(); + rc = stm32_get_DHCP_lease_state(); + + if (rc != _dhcp_lease_state) { + switch (_dhcp_lease_state) { + case DHCP_CHECK_NONE: + _dhcp_lease_state = rc; + rc = DHCP_CHECK_NONE; + break; + + case DHCP_CHECK_RENEW_OK: + _dhcp_lease_state = rc; + if (rc == DHCP_CHECK_NONE) { + rc = DHCP_CHECK_RENEW_OK; + } else { + rc = DHCP_CHECK_RENEW_FAIL; + } + break; + + case DHCP_CHECK_REBIND_OK: + _dhcp_lease_state = rc; + if (rc == DHCP_CHECK_NONE) { + rc = DHCP_CHECK_REBIND_OK; + } else { + rc = DHCP_CHECK_REBIND_FAIL; + } + break; + + default: + _dhcp_lease_state = DHCP_CHECK_NONE; + break; + } + } + + return rc; +} + +IPAddress DhcpClass::getLocalIp() +{ + return IPAddress(stm32_eth_get_ipaddr()); +} + +IPAddress DhcpClass::getSubnetMask() +{ + return IPAddress(stm32_eth_get_netmaskaddr()); +} + +IPAddress DhcpClass::getGatewayIp() +{ + return IPAddress(stm32_eth_get_gwaddr()); +} + +IPAddress DhcpClass::getDhcpServerIp() +{ + return IPAddress(stm32_eth_get_dhcpaddr()); +} + +IPAddress DhcpClass::getDnsServerIp() +{ + return IPAddress(stm32_eth_get_dnsaddr()); +} diff --git a/src/Dhcp.h b/src/Dhcp.h index 089fbde..1467b18 100644 --- a/src/Dhcp.h +++ b/src/Dhcp.h @@ -1,45 +1,45 @@ -// DHCP Library v0.3 - April 25, 2009 -// Author: Jordan Terrell - blog.jordanterrell.com - -#ifndef Dhcp_h -#define Dhcp_h - -#include "EthernetUdp.h" - -/* DHCP state machine. */ -#define STATE_DHCP_STOP DHCP_OFF -#define STATE_DHCP_START DHCP_START -#define STATE_DHCP_DISCOVER DHCP_WAIT_ADDRESS -#define STATE_DHCP_REQUEST 0 -#define STATE_DHCP_LEASED DHCP_ADDRESS_ASSIGNED -#define STATE_DHCP_REREQUEST 0 -#define STATE_DHCP_RELEASE DHCP_ASK_RELEASE - -#define DHCP_CHECK_NONE (0) -#define DHCP_CHECK_RENEW_FAIL (1) -#define DHCP_CHECK_RENEW_OK (2) -#define DHCP_CHECK_REBIND_FAIL (3) -#define DHCP_CHECK_REBIND_OK (4) - -class DhcpClass { -private: - uint8_t _dhcpMacAddr[6]; - unsigned long _timeout; - uint8_t _dhcp_lease_state; - uint8_t _dhcp_state; - - int request_DHCP_lease(); - void reset_DHCP_lease(); - -public: - IPAddress getLocalIp(); - IPAddress getSubnetMask(); - IPAddress getGatewayIp(); - IPAddress getDhcpServerIp(); - IPAddress getDnsServerIp(); - - int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); - int checkLease(); -}; - -#endif +// DHCP Library v0.3 - April 25, 2009 +// Author: Jordan Terrell - blog.jordanterrell.com + +#ifndef Dhcp_h +#define Dhcp_h + +#include "EthernetUdp.h" + +/* DHCP state machine. */ +#define STATE_DHCP_STOP DHCP_OFF +#define STATE_DHCP_START DHCP_START +#define STATE_DHCP_DISCOVER DHCP_WAIT_ADDRESS +#define STATE_DHCP_REQUEST 0 +#define STATE_DHCP_LEASED DHCP_ADDRESS_ASSIGNED +#define STATE_DHCP_REREQUEST 0 +#define STATE_DHCP_RELEASE DHCP_ASK_RELEASE + +#define DHCP_CHECK_NONE (0) +#define DHCP_CHECK_RENEW_FAIL (1) +#define DHCP_CHECK_RENEW_OK (2) +#define DHCP_CHECK_REBIND_FAIL (3) +#define DHCP_CHECK_REBIND_OK (4) + +class DhcpClass { + private: + uint8_t _dhcpMacAddr[6]; + unsigned long _timeout; + uint8_t _dhcp_lease_state; + uint8_t _dhcp_state; + + int request_DHCP_lease(); + void reset_DHCP_lease(); + + public: + IPAddress getLocalIp(); + IPAddress getSubnetMask(); + IPAddress getGatewayIp(); + IPAddress getDhcpServerIp(); + IPAddress getDnsServerIp(); + + int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + int checkLease(); +}; + +#endif diff --git a/src/Dns.cpp b/src/Dns.cpp index 434c139..717b24b 100644 --- a/src/Dns.cpp +++ b/src/Dns.cpp @@ -16,89 +16,82 @@ #define TRUNCATED -3 #define INVALID_RESPONSE -4 -void DNSClient::begin(const IPAddress& aDNSServer) +void DNSClient::begin(const IPAddress &aDNSServer) { - iDNSServer = aDNSServer; - stm32_dns_init(iDNSServer.raw_address()); + iDNSServer = aDNSServer; + stm32_dns_init(iDNSServer.raw_address()); } -int DNSClient::inet_aton(const char* address, IPAddress& result) +int DNSClient::inet_aton(const char *address, IPAddress &result) { - uint16_t acc = 0; // Accumulator - uint8_t dots = 0; - - if(address == NULL) - return 0; - - while (*address) - { - char c = *address++; - if (c >= '0' && c <= '9') - { - acc = acc * 10 + (c - '0'); - if (acc > 255) { - // Value out of [0..255] range - return 0; - } - } - else if (c == '.') - { - if (dots == 3) { - // Too much dots (there must be 3 dots) - return 0; - } - result[dots++] = acc; - acc = 0; - } - else - { - // Invalid char - return 0; - } - } - - if (dots != 3) { - // Too few dots (there must be 3 dots) + uint16_t acc = 0; // Accumulator + uint8_t dots = 0; + + if (address == NULL) { + return 0; + } + + while (*address) { + char c = *address++; + if (c >= '0' && c <= '9') { + acc = acc * 10 + (c - '0'); + if (acc > 255) { + // Value out of [0..255] range return 0; + } + } else if (c == '.') { + if (dots == 3) { + // Too much dots (there must be 3 dots) + return 0; + } + result[dots++] = acc; + acc = 0; + } else { + // Invalid char + return 0; } - result[3] = acc; - return 1; + } + + if (dots != 3) { + // Too few dots (there must be 3 dots) + return 0; + } + result[3] = acc; + return 1; } -int DNSClient::getHostByName(const char* aHostname, IPAddress& aResult) +int DNSClient::getHostByName(const char *aHostname, IPAddress &aResult) { - int ret = 0; - uint32_t ipResult = 0; - - // See if it's a numeric IP address - if (inet_aton(aHostname, aResult)) - { - // It is, our work here is done - return SUCCESS; - } + int ret = 0; + uint32_t ipResult = 0; - // Check we've got a valid DNS server to use - if (iDNSServer == INADDR_NONE) - { - return INVALID_SERVER; - } + // See if it's a numeric IP address + if (inet_aton(aHostname, aResult)) { + // It is, our work here is done + return SUCCESS; + } + + // Check we've got a valid DNS server to use + if (iDNSServer == INADDR_NONE) { + return INVALID_SERVER; + } - ret = stm32_dns_gethostbyname(aHostname, &ipResult); - aResult = IPAddress(ipResult); + ret = stm32_dns_gethostbyname(aHostname, &ipResult); + aResult = IPAddress(ipResult); - return ret; + return ret; } /* Deprecated function. Do not use anymore. */ -uint16_t DNSClient::BuildRequest(const char* aName) +uint16_t DNSClient::BuildRequest(const char *aName) { UNUSED(aName); return 0; } /* Deprecated function. Do not use anymore. */ -uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress) +uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress &aAddress) { UNUSED(aTimeout); UNUSED(aAddress); diff --git a/src/Dns.h b/src/Dns.h index 6f2773f..5de2d4f 100644 --- a/src/Dns.h +++ b/src/Dns.h @@ -1,39 +1,38 @@ -// Arduino DNS client for WizNet5100-based Ethernet shield -// (c) Copyright 2009-2010 MCQN Ltd. -// Released under Apache License, version 2.0 - -#ifndef DNSClient_h -#define DNSClient_h - -#include - -class DNSClient -{ -public: - // ctor - void begin(const IPAddress& aDNSServer); - - /** Convert a numeric IP address string into a four-byte IP address. - @param aIPAddrString IP address to convert - @param aResult IPAddress structure to store the returned IP address - @result 1 if aIPAddrString was successfully converted to an IP address, - else error code - */ - int inet_aton(const char *aIPAddrString, IPAddress& aResult); - - /** Resolve the given hostname to an IP address. - @param aHostname Name to be resolved - @param aResult IPAddress structure to store the returned IP address - @result 1 if aIPAddrString was successfully converted to an IP address, - else error code - */ - int getHostByName(const char* aHostname, IPAddress& aResult); - -protected: - uint16_t BuildRequest(const char* aName); - uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress); - - IPAddress iDNSServer; -}; - -#endif +// Arduino DNS client for WizNet5100-based Ethernet shield +// (c) Copyright 2009-2010 MCQN Ltd. +// Released under Apache License, version 2.0 + +#ifndef DNSClient_h +#define DNSClient_h + +#include + +class DNSClient { + public: + // ctor + void begin(const IPAddress &aDNSServer); + + /** Convert a numeric IP address string into a four-byte IP address. + @param aIPAddrString IP address to convert + @param aResult IPAddress structure to store the returned IP address + @result 1 if aIPAddrString was successfully converted to an IP address, + else error code + */ + int inet_aton(const char *aIPAddrString, IPAddress &aResult); + + /** Resolve the given hostname to an IP address. + @param aHostname Name to be resolved + @param aResult IPAddress structure to store the returned IP address + @result 1 if aIPAddrString was successfully converted to an IP address, + else error code + */ + int getHostByName(const char *aHostname, IPAddress &aResult); + + protected: + uint16_t BuildRequest(const char *aName); + uint16_t ProcessResponse(uint16_t aTimeout, IPAddress &aAddress); + + IPAddress iDNSServer; +}; + +#endif diff --git a/src/EthernetClient.cpp b/src/EthernetClient.cpp index 53c0505..5db2e47 100644 --- a/src/EthernetClient.cpp +++ b/src/EthernetClient.cpp @@ -1,5 +1,5 @@ extern "C" { - #include "string.h" +#include "string.h" } #include "Arduino.h" @@ -10,21 +10,25 @@ extern "C" { #include "Dns.h" EthernetClient::EthernetClient() - :_tcp_client(NULL) { + : _tcp_client(NULL) +{ } /* Deprecated constructor. Keeps compatibility with W5100 architecture sketches but sock is ignored. */ EthernetClient::EthernetClient(uint8_t sock) - :_tcp_client(NULL) { + : _tcp_client(NULL) +{ UNUSED(sock); } -EthernetClient::EthernetClient(struct tcp_struct *tcpClient) { +EthernetClient::EthernetClient(struct tcp_struct *tcpClient) +{ _tcp_client = tcpClient; } -int EthernetClient::connect(const char* host, uint16_t port) { +int EthernetClient::connect(const char *host, uint16_t port) +{ // Look up the host first int ret = 0; DNSClient dns; @@ -39,20 +43,21 @@ int EthernetClient::connect(const char* host, uint16_t port) { } } -int EthernetClient::connect(IPAddress ip, uint16_t port) { - if(_tcp_client == NULL) { +int EthernetClient::connect(IPAddress ip, uint16_t port) +{ + if (_tcp_client == NULL) { /* Allocates memory for client */ _tcp_client = (struct tcp_struct *)mem_malloc(sizeof(struct tcp_struct)); - if(_tcp_client == NULL) { - return 0; + if (_tcp_client == NULL) { + return 0; } } /* Creates a new TCP protocol control block */ _tcp_client->pcb = tcp_new(); - if(_tcp_client->pcb == NULL) { + if (_tcp_client->pcb == NULL) { return 0; } @@ -62,15 +67,15 @@ int EthernetClient::connect(IPAddress ip, uint16_t port) { ip_addr_t ipaddr; tcp_arg(_tcp_client->pcb, _tcp_client); - if(ERR_OK != tcp_connect(_tcp_client->pcb, u8_to_ip_addr(rawIPAddress(ip), &ipaddr), port, &tcp_connected_callback)) { + if (ERR_OK != tcp_connect(_tcp_client->pcb, u8_to_ip_addr(rawIPAddress(ip), &ipaddr), port, &tcp_connected_callback)) { stop(); return 0; } uint32_t startTime = millis(); - while(_tcp_client->state == TCP_NONE) { + while (_tcp_client->state == TCP_NONE) { stm32_eth_scheduler(); - if((_tcp_client->state == TCP_CLOSING) || ((millis() - startTime) >= 10000)) { + if ((_tcp_client->state == TCP_CLOSING) || ((millis() - startTime) >= 10000)) { stop(); return 0; } @@ -79,20 +84,22 @@ int EthernetClient::connect(IPAddress ip, uint16_t port) { return 1; } -size_t EthernetClient::write(uint8_t b) { +size_t EthernetClient::write(uint8_t b) +{ return write(&b, 1); } -size_t EthernetClient::write(const uint8_t *buf, size_t size) { - if( (_tcp_client == NULL) || (_tcp_client->pcb == NULL) || +size_t EthernetClient::write(const uint8_t *buf, size_t size) +{ + if ((_tcp_client == NULL) || (_tcp_client->pcb == NULL) || (buf == NULL) || (size == 0)) { return 0; } /* If client not connected or accepted, it can't write because connection is not ready */ - if((_tcp_client->state != TCP_ACCEPTED) && - (_tcp_client->state != TCP_CONNECTED)) { + if ((_tcp_client->state != TCP_ACCEPTED) && + (_tcp_client->state != TCP_CONNECTED)) { return 0; } @@ -101,45 +108,46 @@ size_t EthernetClient::write(const uint8_t *buf, size_t size) { size_t bytes_left = size; err_t res; - do{ + do { max_send_size = tcp_sndbuf(_tcp_client->pcb); bytes_to_send = bytes_left > max_send_size ? max_send_size : bytes_left; - if(bytes_to_send > 0){ + if (bytes_to_send > 0) { res = tcp_write(_tcp_client->pcb, &buf[bytes_sent], bytes_to_send, TCP_WRITE_FLAG_COPY); - if(res == ERR_OK){ + if (res == ERR_OK) { bytes_sent += bytes_to_send; bytes_left = size - bytes_sent; - } - else if(res != ERR_MEM){ + } else if (res != ERR_MEM) { // other error, cannot continue return 0; } } //Force to send data right now! - if(ERR_OK != tcp_output(_tcp_client->pcb)) { + if (ERR_OK != tcp_output(_tcp_client->pcb)) { return 0; } stm32_eth_scheduler(); - } while(bytes_sent != size); + } while (bytes_sent != size); return size; } -int EthernetClient::available() { +int EthernetClient::available() +{ stm32_eth_scheduler(); - if(_tcp_client != NULL) { + if (_tcp_client != NULL) { return _tcp_client->data.available; } return 0; } -int EthernetClient::read() { +int EthernetClient::read() +{ uint8_t b; - if((_tcp_client != NULL) && (_tcp_client->data.p != NULL)) { + if ((_tcp_client != NULL) && (_tcp_client->data.p != NULL)) { stm32_get_data(&(_tcp_client->data), &b, 1); return b; } @@ -147,49 +155,56 @@ int EthernetClient::read() { return -1; } -int EthernetClient::read(uint8_t *buf, size_t size) { - if((_tcp_client != NULL) && (_tcp_client->data.p != NULL)) { +int EthernetClient::read(uint8_t *buf, size_t size) +{ + if ((_tcp_client != NULL) && (_tcp_client->data.p != NULL)) { return stm32_get_data(&(_tcp_client->data), buf, size); } return -1; } -int EthernetClient::peek() { +int EthernetClient::peek() +{ uint8_t b; // Unlike recv, peek doesn't check to see if there's any data available, so we must - if (!available()) + if (!available()) { return -1; + } b = pbuf_get_at(_tcp_client->data.p, 0); return b; } -void EthernetClient::flush() { - if((_tcp_client == NULL) || (_tcp_client->pcb == NULL)) { +void EthernetClient::flush() +{ + if ((_tcp_client == NULL) || (_tcp_client->pcb == NULL)) { return; } tcp_output(_tcp_client->pcb); stm32_eth_scheduler(); } -void EthernetClient::stop() { - if(_tcp_client == NULL) { +void EthernetClient::stop() +{ + if (_tcp_client == NULL) { return; } // close tcp connection if not closed yet - if(status() != TCP_CLOSING) { + if (status() != TCP_CLOSING) { tcp_connection_close(_tcp_client->pcb, _tcp_client); } } -uint8_t EthernetClient::connected() { +uint8_t EthernetClient::connected() +{ uint8_t s = status(); return ((available() && (s == TCP_CLOSING)) || (s == TCP_CONNECTED) || (s == TCP_ACCEPTED)); } -uint8_t EthernetClient::status() { - if(_tcp_client == NULL) { +uint8_t EthernetClient::status() +{ + if (_tcp_client == NULL) { return TCP_NONE; } return _tcp_client->state; @@ -198,17 +213,20 @@ uint8_t EthernetClient::status() { // the next function allows us to use the client returned by // EthernetServer::available() as the condition in an if-statement. -EthernetClient::operator bool() { +EthernetClient::operator bool() +{ return (_tcp_client && (_tcp_client->state != TCP_CLOSING)); } -bool EthernetClient::operator==(const EthernetClient& rhs) { +bool EthernetClient::operator==(const EthernetClient &rhs) +{ return _tcp_client == rhs._tcp_client && _tcp_client->pcb == rhs._tcp_client->pcb; } /* This function is not a function defined by Arduino. This is a function specific to the W5100 architecture. To keep the compatibility we leave it and returns always 0. */ -uint8_t EthernetClient::getSocketNumber() { +uint8_t EthernetClient::getSocketNumber() +{ return 0; } diff --git a/src/EthernetClient.h b/src/EthernetClient.h index 6734b6d..251b580 100644 --- a/src/EthernetClient.h +++ b/src/EthernetClient.h @@ -8,39 +8,57 @@ class EthernetClient : public Client { -public: - EthernetClient(); - EthernetClient(uint8_t sock); - EthernetClient(struct tcp_struct *tcpClient); + public: + EthernetClient(); + EthernetClient(uint8_t sock); + EthernetClient(struct tcp_struct *tcpClient); - uint8_t status(); - virtual int connect(IPAddress ip, uint16_t port); - virtual int connect(const char *host, uint16_t port); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *buf, size_t size); - virtual int available(); - virtual int read(); - virtual int read(uint8_t *buf, size_t size); - virtual int peek(); - virtual void flush(); - virtual void stop(); - virtual uint8_t connected(); - virtual operator bool(); - virtual bool operator==(const bool value) { return bool() == value; } - virtual bool operator!=(const bool value) { return bool() != value; } - virtual bool operator==(const EthernetClient&); - virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); }; - uint8_t getSocketNumber(); - virtual uint16_t localPort() { return (_tcp_client->pcb->local_port); }; - virtual IPAddress remoteIP() { return (IPAddress(_tcp_client->pcb->remote_ip.addr)); }; - virtual uint16_t remotePort() { return (_tcp_client->pcb->remote_port); }; + uint8_t status(); + virtual int connect(IPAddress ip, uint16_t port); + virtual int connect(const char *host, uint16_t port); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + virtual int available(); + virtual int read(); + virtual int read(uint8_t *buf, size_t size); + virtual int peek(); + virtual void flush(); + virtual void stop(); + virtual uint8_t connected(); + virtual operator bool(); + virtual bool operator==(const bool value) + { + return bool() == value; + } + virtual bool operator!=(const bool value) + { + return bool() != value; + } + virtual bool operator==(const EthernetClient &); + virtual bool operator!=(const EthernetClient &rhs) + { + return !this->operator==(rhs); + }; + uint8_t getSocketNumber(); + virtual uint16_t localPort() + { + return (_tcp_client->pcb->local_port); + }; + virtual IPAddress remoteIP() + { + return (IPAddress(_tcp_client->pcb->remote_ip.addr)); + }; + virtual uint16_t remotePort() + { + return (_tcp_client->pcb->remote_port); + }; - friend class EthernetServer; + friend class EthernetServer; - using Print::write; + using Print::write; -private: - struct tcp_struct *_tcp_client; + private: + struct tcp_struct *_tcp_client; }; #endif diff --git a/src/EthernetServer.cpp b/src/EthernetServer.cpp index 18ff147..e006b83 100644 --- a/src/EthernetServer.cpp +++ b/src/EthernetServer.cpp @@ -15,20 +15,20 @@ EthernetServer::EthernetServer(uint16_t port) void EthernetServer::begin() { - if(_tcp_server.pcb != NULL) { + if (_tcp_server.pcb != NULL) { return; } _tcp_server.pcb = tcp_new(); - if(_tcp_server.pcb == NULL) { + if (_tcp_server.pcb == NULL) { return; } tcp_arg(_tcp_server.pcb, &_tcp_client); _tcp_server.state = TCP_NONE; - if(ERR_OK != tcp_bind(_tcp_server.pcb, IP_ADDR_ANY, _port)) { + if (ERR_OK != tcp_bind(_tcp_server.pcb, IP_ADDR_ANY, _port)) { memp_free(MEMP_TCP_PCB, _tcp_server.pcb); _tcp_server.pcb = NULL; return; @@ -42,13 +42,13 @@ void EthernetServer::accept() { /* Free client if disconnected */ for (int n = 0; n < MAX_CLIENT; n++) { - if(_tcp_client[n] != NULL) { - EthernetClient client(_tcp_client[n]); - if (client.status() == TCP_CLOSING) { - mem_free(_tcp_client[n]); - _tcp_client[n] = NULL; - } + if (_tcp_client[n] != NULL) { + EthernetClient client(_tcp_client[n]); + if (client.status() == TCP_CLOSING) { + mem_free(_tcp_client[n]); + _tcp_client[n] = NULL; } + } } } @@ -57,8 +57,8 @@ EthernetClient EthernetServer::available() accept(); for (int n = 0; n < MAX_CLIENT; n++) { - if(_tcp_client[n] != NULL) { - if(_tcp_client[n]->pcb != NULL) { + if (_tcp_client[n] != NULL) { + if (_tcp_client[n]->pcb != NULL) { EthernetClient client(_tcp_client[n]); uint8_t s = client.status(); if (s == TCP_ACCEPTED) { @@ -86,8 +86,8 @@ size_t EthernetServer::write(const uint8_t *buffer, size_t size) accept(); for (int n = 0; n < MAX_CLIENT; n++) { - if(_tcp_client[n] != NULL) { - if(_tcp_client[n]->pcb != NULL) { + if (_tcp_client[n] != NULL) { + if (_tcp_client[n]->pcb != NULL) { EthernetClient client(_tcp_client[n]); uint8_t s = client.status(); if (s == TCP_ACCEPTED) { diff --git a/src/EthernetServer.h b/src/EthernetServer.h index fb42c43..60fac5b 100644 --- a/src/EthernetServer.h +++ b/src/EthernetServer.h @@ -6,20 +6,20 @@ class EthernetClient; class EthernetServer : -public Server { -private: - uint16_t _port; - struct tcp_struct _tcp_server; - struct tcp_struct *_tcp_client[MAX_CLIENT]; - - void accept(void); -public: - EthernetServer(uint16_t port = 80); - EthernetClient available(); - virtual void begin(); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *buf, size_t size); - using Print::write; + public Server { + private: + uint16_t _port; + struct tcp_struct _tcp_server; + struct tcp_struct *_tcp_client[MAX_CLIENT]; + + void accept(void); + public: + EthernetServer(uint16_t port = 80); + EthernetClient available(); + virtual void begin(); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + using Print::write; }; #endif diff --git a/src/EthernetUdp.cpp b/src/EthernetUdp.cpp old mode 100755 new mode 100644 index c4bfff7..78df02e --- a/src/EthernetUdp.cpp +++ b/src/EthernetUdp.cpp @@ -36,20 +36,22 @@ EthernetUDP::EthernetUDP() {} /* Start EthernetUDP socket, listening at local port PORT */ -uint8_t EthernetUDP::begin(uint16_t port) { +uint8_t EthernetUDP::begin(uint16_t port) +{ return begin(Ethernet.localIP(), port); } /* Start EthernetUDP socket, listening at local IP ip and port PORT */ -uint8_t EthernetUDP::begin(IPAddress ip, uint16_t port, bool multicast) { +uint8_t EthernetUDP::begin(IPAddress ip, uint16_t port, bool multicast) +{ // Can create a single udp connection per socket - if(_udp.pcb != NULL) { + if (_udp.pcb != NULL) { return 0; } _udp.pcb = udp_new(); - if(_udp.pcb == NULL) { + if (_udp.pcb == NULL) { return 0; } @@ -62,14 +64,14 @@ uint8_t EthernetUDP::begin(IPAddress ip, uint16_t port, bool multicast) { err = udp_bind(_udp.pcb, &ipaddr, port); } - if(ERR_OK != err) { + if (ERR_OK != err) { stop(); return 0; } #if LWIP_IGMP if ((multicast) && (ERR_OK != igmp_joingroup(IP_ADDR_ANY, &ipaddr))) { - return 0; + return 0; } #endif udp_recv(_udp.pcb, &udp_receive_callback, &_udp); @@ -84,14 +86,15 @@ uint8_t EthernetUDP::begin(IPAddress ip, uint16_t port, bool multicast) { /* return number of bytes available in the current packet, will return zero if parsePacket hasn't been called yet */ -int EthernetUDP::available() { +int EthernetUDP::available() +{ return _remaining; } /* Release any resources being used by this EthernetUDP instance */ void EthernetUDP::stop() { - if(_udp.pcb != NULL) { + if (_udp.pcb != NULL) { udp_disconnect(_udp.pcb); udp_remove(_udp.pcb); _udp.pcb = NULL; @@ -118,7 +121,7 @@ int EthernetUDP::beginPacket(const char *host, uint16_t port) int EthernetUDP::beginPacket(IPAddress ip, uint16_t port) { - if(_udp.pcb == NULL) { + if (_udp.pcb == NULL) { return 0; } @@ -133,12 +136,12 @@ int EthernetUDP::beginPacket(IPAddress ip, uint16_t port) int EthernetUDP::endPacket() { - if((_udp.pcb == NULL) || (_data == NULL)) { + if ((_udp.pcb == NULL) || (_data == NULL)) { return 0; } ip_addr_t ipaddr; - if(ERR_OK != udp_sendto(_udp.pcb, _data, u8_to_ip_addr(rawIPAddress(_sendtoIP), &ipaddr), _sendtoPort)) { + if (ERR_OK != udp_sendto(_udp.pcb, _data, u8_to_ip_addr(rawIPAddress(_sendtoIP), &ipaddr), _sendtoPort)) { _data = stm32_free_data(_data); return 0; } @@ -157,7 +160,7 @@ size_t EthernetUDP::write(uint8_t byte) size_t EthernetUDP::write(const uint8_t *buffer, size_t size) { _data = stm32_new_data(_data, buffer, size); - if(_data == NULL) { + if (_data == NULL) { return 0; } @@ -176,8 +179,7 @@ int EthernetUDP::parsePacket() stm32_eth_scheduler(); - if (_udp.data.available > 0) - { + if (_udp.data.available > 0) { _remoteIP = IPAddress(ip_addr_to_u32(&(_udp.ip))); _remotePort = _udp.port; _remaining = _udp.data.available; @@ -192,44 +194,39 @@ int EthernetUDP::read() { uint8_t byte; - if(_udp.data.p == NULL) { + if (_udp.data.p == NULL) { return -1; } - if (_remaining > 0) - { - if(read(&byte, 1) > 0) + if (_remaining > 0) { + if (read(&byte, 1) > 0) { return byte; + } } // If we get here, there's no data available return -1; } -int EthernetUDP::read(unsigned char* buffer, size_t len) +int EthernetUDP::read(unsigned char *buffer, size_t len) { - if(_udp.data.p == NULL) { + if (_udp.data.p == NULL) { return -1; } - if (_remaining > 0) - { + if (_remaining > 0) { int got; - if (_remaining <= len) - { + if (_remaining <= len) { // data should fit in the buffer got = (int)stm32_get_data(&(_udp.data), (uint8_t *)buffer, _remaining); - } - else - { + } else { // too much data for the buffer, // grab as much as will fit got = (int)stm32_get_data(&(_udp.data), (uint8_t *)buffer, len); } - if (got > 0) - { + if (got > 0) { _remaining -= got; return got; } @@ -247,8 +244,9 @@ int EthernetUDP::peek() // Unlike recv, peek doesn't check to see if there's any data available, so we must. // If the user hasn't called parsePacket yet then return nothing otherwise they // may get the UDP header - if (!_remaining) + if (!_remaining) { return -1; + } b = pbuf_get_at(_udp.data.p, 0); return b; } @@ -265,7 +263,8 @@ uint8_t EthernetUDP::beginMulticast(IPAddress ip, uint16_t port) } #if LWIP_UDP -void EthernetUDP::onDataArrival( std::function onDataArrival_fn){ +void EthernetUDP::onDataArrival(std::function onDataArrival_fn) +{ _udp.onDataArrival = onDataArrival_fn; } #endif diff --git a/src/EthernetUdp.h b/src/EthernetUdp.h index 0a1d2f9..a9864cb 100644 --- a/src/EthernetUdp.h +++ b/src/EthernetUdp.h @@ -45,66 +45,75 @@ #define UDP_TX_PACKET_MAX_SIZE 24 class EthernetUDP : public UDP { -private: - uint16_t _port; // local port to listen on - IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed - uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed - IPAddress _sendtoIP; // the remote IP address set by beginPacket - uint16_t _sendtoPort; // the remote port set by beginPacket + private: + uint16_t _port; // local port to listen on + IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed + uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed + IPAddress _sendtoIP; // the remote IP address set by beginPacket + uint16_t _sendtoPort; // the remote port set by beginPacket - struct pbuf *_data; //pbuf for data to send - struct udp_struct _udp; //udp settings + struct pbuf *_data; //pbuf for data to send + struct udp_struct _udp; //udp settings -protected: - uint16_t _remaining; // remaining bytes of incoming packet yet to be processed + protected: + uint16_t _remaining; // remaining bytes of incoming packet yet to be processed -public: - EthernetUDP(); // Constructor - virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual uint8_t begin(IPAddress, uint16_t, bool multicast = false); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual uint8_t beginMulticast(IPAddress, uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual void stop(); // Finish with the UDP socket + public: + EthernetUDP(); // Constructor + virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual uint8_t begin(IPAddress, uint16_t, bool multicast = false); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual uint8_t beginMulticast(IPAddress, uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual void stop(); // Finish with the UDP socket - // Sending UDP packets + // Sending UDP packets - // Start building up a packet to send to the remote host specific in ip and port - // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port - virtual int beginPacket(IPAddress ip, uint16_t port); - // Start building up a packet to send to the remote host specific in host and port - // Returns 1 if successful, 0 if there was a problem resolving the hostname or port - virtual int beginPacket(const char *host, uint16_t port); - // Finish off this packet and send it - // Returns 1 if the packet was sent successfully, 0 if there was an error - virtual int endPacket(); - // Write a single byte into the packet - virtual size_t write(uint8_t); - // Write size bytes from buffer into the packet - virtual size_t write(const uint8_t *buffer, size_t size); + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + virtual int beginPacket(IPAddress ip, uint16_t port); + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + virtual int beginPacket(const char *host, uint16_t port); + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + virtual int endPacket(); + // Write a single byte into the packet + virtual size_t write(uint8_t); + // Write size bytes from buffer into the packet + virtual size_t write(const uint8_t *buffer, size_t size); - using Print::write; + using Print::write; - // Start processing the next available incoming packet - // Returns the size of the packet in bytes, or 0 if no packets are available - virtual int parsePacket(); - // Number of bytes remaining in the current packet - virtual int available(); - // Read a single byte from the current packet - virtual int read(); - // Read up to len bytes from the current packet and place them into buffer - // Returns the number of bytes read, or 0 if none are available - virtual int read(unsigned char* buffer, size_t len); - // Read up to len characters from the current packet and place them into buffer - // Returns the number of characters read, or 0 if none are available - virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); }; - // Return the next byte from the current packet without moving on to the next byte - virtual int peek(); - virtual void flush(); // Finish reading the current packet + // Start processing the next available incoming packet + // Returns the size of the packet in bytes, or 0 if no packets are available + virtual int parsePacket(); + // Number of bytes remaining in the current packet + virtual int available(); + // Read a single byte from the current packet + virtual int read(); + // Read up to len bytes from the current packet and place them into buffer + // Returns the number of bytes read, or 0 if none are available + virtual int read(unsigned char *buffer, size_t len); + // Read up to len characters from the current packet and place them into buffer + // Returns the number of characters read, or 0 if none are available + virtual int read(char *buffer, size_t len) + { + return read((unsigned char *)buffer, len); + }; + // Return the next byte from the current packet without moving on to the next byte + virtual int peek(); + virtual void flush(); // Finish reading the current packet - // Return the IP address of the host who sent the current incoming packet - virtual IPAddress remoteIP() { return _remoteIP; }; - // Return the port of the host who sent the current incoming packet - virtual uint16_t remotePort() { return _remotePort; }; - virtual void onDataArrival( std::function onDataArrival_fn); + // Return the IP address of the host who sent the current incoming packet + virtual IPAddress remoteIP() + { + return _remoteIP; + }; + // Return the port of the host who sent the current incoming packet + virtual uint16_t remotePort() + { + return _remotePort; + }; + virtual void onDataArrival(std::function onDataArrival_fn); }; #endif diff --git a/src/STM32Ethernet.cpp b/src/STM32Ethernet.cpp index 1611815..77313a6 100644 --- a/src/STM32Ethernet.cpp +++ b/src/STM32Ethernet.cpp @@ -9,8 +9,7 @@ int EthernetClass::begin(unsigned long timeout, unsigned long responseTimeout) // Now try to get our config info from a DHCP server int ret = _dhcp->beginWithDHCP(mac_address, timeout, responseTimeout); - if(ret == 1) - { + if (ret == 1) { _dnsServerAddress = _dhcp->getDnsServerIp(); } @@ -59,8 +58,7 @@ int EthernetClass::begin(uint8_t *mac_address, unsigned long timeout, unsigned l // Now try to get our config info from a DHCP server int ret = _dhcp->beginWithDHCP(mac_address, timeout, responseTimeout); - if(ret == 1) - { + if (ret == 1) { _dnsServerAddress = _dhcp->getDnsServerIp(); } MACAddress(mac_address); @@ -106,13 +104,14 @@ EthernetLinkStatus EthernetClass::linkStatus() return (!stm32_eth_is_init()) ? Unknown : (stm32_eth_link_up() ? LinkON : LinkOFF); } -int EthernetClass::maintain(){ +int EthernetClass::maintain() +{ int rc = DHCP_CHECK_NONE; - if(_dhcp != NULL){ + if (_dhcp != NULL) { //we have a pointer to dhcp, use it rc = _dhcp->checkLease(); - switch ( rc ){ + switch (rc) { case DHCP_CHECK_NONE: //nothing done break; @@ -137,7 +136,7 @@ void EthernetClass::schedule(void) stm32_eth_scheduler(); } -uint8_t * EthernetClass::MACAddressDefault(void) +uint8_t *EthernetClass::MACAddressDefault(void) { if ((mac_address[0] + mac_address[1] + mac_address[2] + mac_address[3] + mac_address[4] + mac_address[5]) == 0) { uint32_t baseUID = *(uint32_t *)UID_BASE; @@ -151,7 +150,8 @@ uint8_t * EthernetClass::MACAddressDefault(void) return mac_address; } -void EthernetClass::MACAddress(uint8_t *mac) { +void EthernetClass::MACAddress(uint8_t *mac) +{ mac_address[0] = mac[0]; mac_address[1] = mac[1]; mac_address[2] = mac[2]; @@ -160,7 +160,8 @@ void EthernetClass::MACAddress(uint8_t *mac) { mac_address[5] = mac[5]; } -uint8_t * EthernetClass::MACAddress(void) { +uint8_t *EthernetClass::MACAddress(void) +{ return mac_address; } diff --git a/src/STM32Ethernet.h b/src/STM32Ethernet.h index f9b20eb..502e256 100644 --- a/src/STM32Ethernet.h +++ b/src/STM32Ethernet.h @@ -14,44 +14,44 @@ enum EthernetLinkStatus { }; class EthernetClass { -private: - IPAddress _dnsServerAddress; - DhcpClass* _dhcp; - uint8_t mac_address[6]; - uint8_t * MACAddressDefault(void); - -public: - // Initialise the Ethernet with the internal provided MAC address and gain the rest of the - // configuration through DHCP. - // Returns 0 if the DHCP configuration failed, and 1 if it succeeded - int begin(unsigned long timeout = 60000, unsigned long responseTimeout = 4000); - EthernetLinkStatus linkStatus(); - void begin(IPAddress local_ip); - void begin(IPAddress local_ip, IPAddress subnet); - void begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway); - void begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server); - // Initialise the Ethernet shield to use the provided MAC address and gain the rest of the - // configuration through DHCP. - // Returns 0 if the DHCP configuration failed, and 1 if it succeeded - int begin(uint8_t *mac_address, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); - void begin(uint8_t *mac_address, IPAddress local_ip); - void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server); - void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway); - void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); - - - int maintain(); - void schedule(void); - - void MACAddress(uint8_t *mac); - uint8_t * MACAddress(void); - IPAddress localIP(); - IPAddress subnetMask(); - IPAddress gatewayIP(); - IPAddress dnsServerIP(); - - friend class EthernetClient; - friend class EthernetServer; + private: + IPAddress _dnsServerAddress; + DhcpClass *_dhcp; + uint8_t mac_address[6]; + uint8_t *MACAddressDefault(void); + + public: + // Initialise the Ethernet with the internal provided MAC address and gain the rest of the + // configuration through DHCP. + // Returns 0 if the DHCP configuration failed, and 1 if it succeeded + int begin(unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + EthernetLinkStatus linkStatus(); + void begin(IPAddress local_ip); + void begin(IPAddress local_ip, IPAddress subnet); + void begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway); + void begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server); + // Initialise the Ethernet shield to use the provided MAC address and gain the rest of the + // configuration through DHCP. + // Returns 0 if the DHCP configuration failed, and 1 if it succeeded + int begin(uint8_t *mac_address, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + void begin(uint8_t *mac_address, IPAddress local_ip); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); + + + int maintain(); + void schedule(void); + + void MACAddress(uint8_t *mac); + uint8_t *MACAddress(void); + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); + + friend class EthernetClient; + friend class EthernetServer; }; extern EthernetClass Ethernet; diff --git a/src/lwipopts.h b/src/lwipopts.h index e3fb5f3..09bcbde 100644 --- a/src/lwipopts.h +++ b/src/lwipopts.h @@ -1,21 +1,21 @@ -/* - * @file lwipopts.h - * @author Frederic Pillon for STMicroelectronics. - * @brief Include header file to match Arduino library format - */ - -#ifndef _ARDUINO_LWIPOPTS_H -#define _ARDUINO_LWIPOPTS_H - -/* LwIP specific configuration options. */ -#if __has_include("STM32lwipopts.h") -#include "STM32lwipopts.h" -#else -#if __has_include("lwipopts_extra.h") -#include "lwipopts_extra.h" -#endif -#include "lwipopts_default.h" -#endif - -#endif /* _ARDUINO_LWIPOPTS_H */ - +/* + * @file lwipopts.h + * @author Frederic Pillon for STMicroelectronics. + * @brief Include header file to match Arduino library format + */ + +#ifndef _ARDUINO_LWIPOPTS_H +#define _ARDUINO_LWIPOPTS_H + +/* LwIP specific configuration options. */ +#if __has_include("STM32lwipopts.h") +#include "STM32lwipopts.h" +#else +#if __has_include("lwipopts_extra.h") +#include "lwipopts_extra.h" +#endif +#include "lwipopts_default.h" +#endif + +#endif /* _ARDUINO_LWIPOPTS_H */ + diff --git a/src/lwipopts_default.h b/src/lwipopts_default.h index 0a03e31..f13b274 100644 --- a/src/lwipopts_default.h +++ b/src/lwipopts_default.h @@ -1,241 +1,241 @@ -/** - ****************************************************************************** - * @file lwipopts_default.h - * @author MCD Application Team - * @brief lwIP Options Configuration. - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2017 STMicroelectronics International N.V. - * All rights reserved.

- * - * This software component is licensed by ST under Ultimate Liberty license - * SLA0044, the "License"; You may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * www.st.com/SLA0044 - * - ****************************************************************************** - */ -#ifndef __LWIPOPTS_H__ -#define __LWIPOPTS_H__ - -/** - * NO_SYS==1: Provides VERY minimal functionality. Otherwise, - * use lwIP facilities. - */ -#define NO_SYS 1 - -/** - * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain - * critical regions during buffer allocation, deallocation and memory - * allocation and deallocation. - */ -#define SYS_LIGHTWEIGHT_PROT 0 - -#define LWIP_NOASSERT - -/* ---------- Memory options ---------- */ -/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which - lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2 - byte alignment -> define MEM_ALIGNMENT to 2. */ -#define MEM_ALIGNMENT 4 - -/* MEM_SIZE: the size of the heap memory. If the application will send -a lot of data that needs to be copied, this should be set high. */ -#define MEM_SIZE (10*1024) - -/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application - sends a lot of data out of ROM (or other static memory), this - should be set high. */ -#define MEMP_NUM_PBUF 10 -/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One - per active UDP "connection". */ -#define MEMP_NUM_UDP_PCB 6 -/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP - connections. */ -#define MEMP_NUM_TCP_PCB 10 -/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP - connections. */ -#define MEMP_NUM_TCP_PCB_LISTEN 6 -/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP - segments. */ -#define MEMP_NUM_TCP_SEG 8 -/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active - timeouts. */ -#define MEMP_NUM_SYS_TIMEOUT 10 - - -/* ---------- Pbuf options ---------- */ -/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ -#define PBUF_POOL_SIZE 8 - -/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ -#define PBUF_POOL_BUFSIZE 1524 - - -/* ---------- TCP options ---------- */ -#define LWIP_TCP 1 -#define TCP_TTL 255 -#define LWIP_SO_RCVTIMEO 1 -#define LWIP_SO_RCVRCVTIMEO_NONSTANDARD 1 /* Pass an integer number of ms instead of a timeval struct. */ -#define LWIP_SO_SNDTIMEO 1 -#define LWIP_SO_SNDRCVTIMEO_NONSTANDARD 1 /* Pass an integer number of ms instead of a timeval struct. */ - -/* Controls if TCP should queue segments that arrive out of - order. Define to 0 if your device is low on memory and you are not scared by TCP congestion and latencies. */ -#define TCP_QUEUE_OOSEQ 0 - -/* TCP Maximum segment size. */ -#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */ - -/* TCP sender buffer space (bytes). */ -#define TCP_SND_BUF (4*TCP_MSS) - -/* TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least - as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */ - -#define TCP_SND_QUEUELEN (2* TCP_SND_BUF/TCP_MSS) - -/* TCP receive window. */ -#define TCP_WND (3*TCP_MSS) - -#define LWIP_TCP_KEEPALIVE 1 /* Keep the TCP link active. Important for MQTT/TLS */ -#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 /* Prevent the same port to be used after reset. - Otherwise, the remote host may be confused if the port was not explicitly closed before the reset. */ - - -/* ---------- ICMP options ---------- */ -#define LWIP_ICMP 1 -#define LWIP_RAW 1 /* PING changed to 1 */ -#define DEFAULT_RAW_RECVMBOX_SIZE 3 /* for ICMP PING */ - - -/* ---------- DHCP options ---------- */ -/* Define LWIP_DHCP to 1 if you want DHCP configuration of - interfaces. DHCP is not implemented in lwIP 0.5.1, however, so - turning this on does currently not work. */ -#define LWIP_DHCP 1 - - -/* ---------- UDP options ---------- */ -#define LWIP_UDP 1 -#define UDP_TTL 255 - - -/* ---------- Statistics options ---------- */ -#define LWIP_STATS 0 -#define LWIP_PROVIDE_ERRNO - -/* ---------- link callback options ---------- */ -/* LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface - * whenever the link changes (i.e., link down) - */ -// need for building net_ip.c -#define LWIP_NETIF_HOSTNAME 1 -#define LWIP_NETIF_STATUS_CALLBACK 1 -#define LWIP_NETIF_LINK_CALLBACK 1 -#define LWIP_DHCP_CHECK_LINK_UP 1 - -/* - -------------------------------------- - ---------- Checksum options ---------- - -------------------------------------- -*/ - -/* -The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware: - - To use this feature let the following define uncommented. - - To disable it and process by CPU comment the the checksum. -*/ -#define CHECKSUM_BY_HARDWARE - - -#ifdef CHECKSUM_BY_HARDWARE - /* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/ - #define CHECKSUM_GEN_IP 0 - /* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/ - #define CHECKSUM_GEN_UDP 0 - /* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/ - #define CHECKSUM_GEN_TCP 0 - /* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/ - #define CHECKSUM_CHECK_IP 0 - /* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/ - #define CHECKSUM_CHECK_UDP 0 - /* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/ - #define CHECKSUM_CHECK_TCP 0 - /* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/ - #define CHECKSUM_GEN_ICMP 0 -#else - /* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/ - #define CHECKSUM_GEN_IP 1 - /* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/ - #define CHECKSUM_GEN_UDP 1 - /* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/ - #define CHECKSUM_GEN_TCP 1 - /* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/ - #define CHECKSUM_CHECK_IP 1 - /* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/ - #define CHECKSUM_CHECK_UDP 1 - /* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/ - #define CHECKSUM_CHECK_TCP 1 - /* CHECKSUM_CHECK_ICMP==1: Check checksums by hardware for incoming ICMP packets.*/ - #define CHECKSUM_GEN_ICMP 1 -#endif - - -/* - ---------------------------------------------- - ---------- Sequential layer options ---------- - ---------------------------------------------- -*/ -/** - * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) - */ -#define LWIP_NETCONN 0 - -/* - ------------------------------------ - ---------- Socket options ---------- - ------------------------------------ -*/ -/** - * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) - */ -#define LWIP_SOCKET 0 -#define LWIP_DNS 1 - -/* - ------------------------------------ - ---------- httpd options ---------- - ------------------------------------ -*/ - -/** Set this to 1 to support CGI */ -#define LWIP_HTTPD_CGI 1 - -/** Set this to 1 to support SSI (Server-Side-Includes) */ -#define LWIP_HTTPD_SSI 1 - -/** Set this to 1 to include "fsdata_custom.c" instead of "fsdata.c" for the - * file system (to prevent changing the file included in CVS) */ -#define HTTPD_USE_CUSTOM_FSDATA 1 - -/* - ------------------------------------ - ---------- Custom options ---------- - ------------------------------------ -*/ - -/** Enables the Ethernet peripheral in RMII mode. If not defined, MII mode will - be enabled. Pin mapping must be configured for the selected mode - (see PinMap_Ethernet in PeripheralPins.c). */ -#define ETHERNET_RMII_MODE_CONFIGURATION 1 - -/** Uncomment this line to use the ethernet input in interrupt mode. - * NOTE: LwIP stack documentation recommends to use the polling mode without - * an operating system. */ -//#define ETH_INPUT_USE_IT 1 - -#endif /* __LWIPOPTS_H__ */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +/** + ****************************************************************************** + * @file lwipopts_default.h + * @author MCD Application Team + * @brief lwIP Options Configuration. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2017 STMicroelectronics International N.V. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#define NO_SYS 1 + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#define SYS_LIGHTWEIGHT_PROT 0 + +#define LWIP_NOASSERT + +/* ---------- Memory options ---------- */ +/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which + lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2 + byte alignment -> define MEM_ALIGNMENT to 2. */ +#define MEM_ALIGNMENT 4 + +/* MEM_SIZE: the size of the heap memory. If the application will send +a lot of data that needs to be copied, this should be set high. */ +#define MEM_SIZE (10*1024) + +/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application + sends a lot of data out of ROM (or other static memory), this + should be set high. */ +#define MEMP_NUM_PBUF 10 +/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + per active UDP "connection". */ +#define MEMP_NUM_UDP_PCB 6 +/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP + connections. */ +#define MEMP_NUM_TCP_PCB 10 +/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP + connections. */ +#define MEMP_NUM_TCP_PCB_LISTEN 6 +/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP + segments. */ +#define MEMP_NUM_TCP_SEG 8 +/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active + timeouts. */ +#define MEMP_NUM_SYS_TIMEOUT 10 + + +/* ---------- Pbuf options ---------- */ +/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ +#define PBUF_POOL_SIZE 8 + +/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ +#define PBUF_POOL_BUFSIZE 1524 + + +/* ---------- TCP options ---------- */ +#define LWIP_TCP 1 +#define TCP_TTL 255 +#define LWIP_SO_RCVTIMEO 1 +#define LWIP_SO_RCVRCVTIMEO_NONSTANDARD 1 /* Pass an integer number of ms instead of a timeval struct. */ +#define LWIP_SO_SNDTIMEO 1 +#define LWIP_SO_SNDRCVTIMEO_NONSTANDARD 1 /* Pass an integer number of ms instead of a timeval struct. */ + +/* Controls if TCP should queue segments that arrive out of + order. Define to 0 if your device is low on memory and you are not scared by TCP congestion and latencies. */ +#define TCP_QUEUE_OOSEQ 0 + +/* TCP Maximum segment size. */ +#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */ + +/* TCP sender buffer space (bytes). */ +#define TCP_SND_BUF (4*TCP_MSS) + +/* TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */ + +#define TCP_SND_QUEUELEN (2* TCP_SND_BUF/TCP_MSS) + +/* TCP receive window. */ +#define TCP_WND (3*TCP_MSS) + +#define LWIP_TCP_KEEPALIVE 1 /* Keep the TCP link active. Important for MQTT/TLS */ +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 /* Prevent the same port to be used after reset. + Otherwise, the remote host may be confused if the port was not explicitly closed before the reset. */ + + +/* ---------- ICMP options ---------- */ +#define LWIP_ICMP 1 +#define LWIP_RAW 1 /* PING changed to 1 */ +#define DEFAULT_RAW_RECVMBOX_SIZE 3 /* for ICMP PING */ + + +/* ---------- DHCP options ---------- */ +/* Define LWIP_DHCP to 1 if you want DHCP configuration of + interfaces. DHCP is not implemented in lwIP 0.5.1, however, so + turning this on does currently not work. */ +#define LWIP_DHCP 1 + + +/* ---------- UDP options ---------- */ +#define LWIP_UDP 1 +#define UDP_TTL 255 + + +/* ---------- Statistics options ---------- */ +#define LWIP_STATS 0 +#define LWIP_PROVIDE_ERRNO + +/* ---------- link callback options ---------- */ +/* LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +// need for building net_ip.c +#define LWIP_NETIF_HOSTNAME 1 +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define LWIP_DHCP_CHECK_LINK_UP 1 + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ + +/* +The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware: + - To use this feature let the following define uncommented. + - To disable it and process by CPU comment the the checksum. +*/ +#define CHECKSUM_BY_HARDWARE + + +#ifdef CHECKSUM_BY_HARDWARE +/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/ +#define CHECKSUM_GEN_IP 0 +/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/ +#define CHECKSUM_GEN_UDP 0 +/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/ +#define CHECKSUM_GEN_TCP 0 +/* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/ +#define CHECKSUM_CHECK_IP 0 +/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/ +#define CHECKSUM_CHECK_UDP 0 +/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/ +#define CHECKSUM_CHECK_TCP 0 +/* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/ +#define CHECKSUM_GEN_ICMP 0 +#else +/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/ +#define CHECKSUM_GEN_IP 1 +/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/ +#define CHECKSUM_GEN_UDP 1 +/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/ +#define CHECKSUM_GEN_TCP 1 +/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/ +#define CHECKSUM_CHECK_IP 1 +/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/ +#define CHECKSUM_CHECK_UDP 1 +/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/ +#define CHECKSUM_CHECK_TCP 1 +/* CHECKSUM_CHECK_ICMP==1: Check checksums by hardware for incoming ICMP packets.*/ +#define CHECKSUM_GEN_ICMP 1 +#endif + + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#define LWIP_NETCONN 0 + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#define LWIP_SOCKET 0 +#define LWIP_DNS 1 + +/* + ------------------------------------ + ---------- httpd options ---------- + ------------------------------------ +*/ + +/** Set this to 1 to support CGI */ +#define LWIP_HTTPD_CGI 1 + +/** Set this to 1 to support SSI (Server-Side-Includes) */ +#define LWIP_HTTPD_SSI 1 + +/** Set this to 1 to include "fsdata_custom.c" instead of "fsdata.c" for the + * file system (to prevent changing the file included in CVS) */ +#define HTTPD_USE_CUSTOM_FSDATA 1 + +/* + ------------------------------------ + ---------- Custom options ---------- + ------------------------------------ +*/ + +/** Enables the Ethernet peripheral in RMII mode. If not defined, MII mode will + be enabled. Pin mapping must be configured for the selected mode + (see PinMap_Ethernet in PeripheralPins.c). */ +#define ETHERNET_RMII_MODE_CONFIGURATION 1 + +/** Uncomment this line to use the ethernet input in interrupt mode. + * NOTE: LwIP stack documentation recommends to use the polling mode without + * an operating system. */ +//#define ETH_INPUT_USE_IT 1 + +#endif /* __LWIPOPTS_H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/utility/ethernetif.cpp b/src/utility/ethernetif.cpp index 6ad4407..346a0ad 100644 --- a/src/utility/ethernetif.cpp +++ b/src/utility/ethernetif.cpp @@ -1,741 +1,717 @@ -/** - ****************************************************************************** - * @file ethernetif.c - * @author MCD Application Team & Wi6Labs - * @version V1.5.0 - * @date 20-june-2017 - * @brief This file implements Ethernet network interface drivers for lwIP - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2017 STMicroelectronics International N.V. - * All rights reserved.

- * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: - * - * 1. Redistribution of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. - * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ -/* Includes ------------------------------------------------------------------*/ -#include "stm32_def.h" -#include "lwip/timeouts.h" -#include "netif/etharp.h" -#include "ethernetif.h" -#include -#include "PeripheralPins.h" -#include "lwip/igmp.h" -#include "stm32_eth.h" -#if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01050000) -#include "variant.h" -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Network interface name */ -#define IFNAME0 's' -#define IFNAME1 't' - -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -#if defined ( __ICCARM__ ) /*!< IAR Compiler */ - #pragma data_alignment=4 -#endif -__ALIGN_BEGIN ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __ALIGN_END;/* Ethernet Rx MA Descriptor */ - -#if defined ( __ICCARM__ ) /*!< IAR Compiler */ - #pragma data_alignment=4 -#endif -__ALIGN_BEGIN ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] __ALIGN_END;/* Ethernet Tx DMA Descriptor */ - -#if defined ( __ICCARM__ ) /*!< IAR Compiler */ - #pragma data_alignment=4 -#endif -__ALIGN_BEGIN uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __ALIGN_END; /* Ethernet Receive Buffer */ - -#if defined ( __ICCARM__ ) /*!< IAR Compiler */ - #pragma data_alignment=4 -#endif -__ALIGN_BEGIN uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END; /* Ethernet Transmit Buffer */ - -static ETH_HandleTypeDef EthHandle; - -static uint8_t macaddress[6]= { MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5 }; - -#if LWIP_IGMP -uint32_t ETH_HashTableHigh=0x0; -uint32_t ETH_HashTableLow=0x0; -#endif - -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ -/******************************************************************************* - Ethernet MSP Routines -*******************************************************************************/ -/** - * @brief Initializes the ETH MSP. - * @param heth: ETH handle - * @retval None - */ -void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) -{ - GPIO_InitTypeDef GPIO_InitStructure; - const PinMap* map = PinMap_Ethernet; - PinName pin = pin_pinName(map); - GPIO_TypeDef* port; - - UNUSED(heth); - -/* Ethernet pins configuration ************************************************/ - - if(map != NULL) { - while(pin != NC) { - /* Set port clock */ - port = set_GPIO_Port_Clock(STM_PORT(pin)); - - /* pin configuration */ - GPIO_InitStructure.Pin = STM_GPIO_PIN(pin); - GPIO_InitStructure.Mode = STM_PIN_MODE(pinmap_function(pin, PinMap_Ethernet)); - GPIO_InitStructure.Pull = STM_PIN_PUPD(pinmap_function(pin, PinMap_Ethernet)); - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStructure.Alternate = STM_PIN_AFNUM(pinmap_function(pin, PinMap_Ethernet)); - HAL_GPIO_Init(port, &GPIO_InitStructure); - - pin = pin_pinName(++map); - } - } - -#ifdef ETH_INPUT_USE_IT - /* Enable the Ethernet global Interrupt */ - HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); - HAL_NVIC_EnableIRQ(ETH_IRQn); -#endif /* ETH_INPUT_USE_IT */ - - /* Enable ETHERNET clock */ - __HAL_RCC_ETH_CLK_ENABLE(); -} - -/******************************************************************************* - LL Driver Interface ( LwIP stack --> ETH) -*******************************************************************************/ -/** - * @brief In this function, the hardware should be initialized. - * Called from ethernetif_init(). - * - * @param netif the already initialized lwip network interface structure - * for this ethernetif - */ -static void low_level_init(struct netif *netif) -{ - uint32_t regvalue; - - EthHandle.Instance = ETH; - EthHandle.Init.MACAddr = macaddress; - EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE; - EthHandle.Init.Speed = ETH_SPEED_100M; - EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX; -#ifdef ETHERNET_RMII_MODE_CONFIGURATION - EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII; -#else - EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII; -#endif /* ETHERNET_RMII_MODE_CONFIGURATION */ -#ifdef ETH_INPUT_USE_IT - EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE; -#else - EthHandle.Init.RxMode = ETH_RXPOLLING_MODE; -#endif /* ETH_INPUT_USE_IT */ - EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE; - EthHandle.Init.PhyAddress = LAN8742A_PHY_ADDRESS; - - /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */ - if (HAL_ETH_Init(&EthHandle) == HAL_OK) - { - /* Set netif link flag */ - netif->flags |= NETIF_FLAG_LINK_UP; - } - - /* Initialize Tx Descriptors list: Chain Mode */ - HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); - - /* Initialize Rx Descriptors list: Chain Mode */ - HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); - - /* set MAC hardware address length */ - netif->hwaddr_len = ETH_HWADDR_LEN; - - /* set MAC hardware address */ - netif->hwaddr[0] = macaddress[0]; - netif->hwaddr[1] = macaddress[1]; - netif->hwaddr[2] = macaddress[2]; - netif->hwaddr[3] = macaddress[3]; - netif->hwaddr[4] = macaddress[4]; - netif->hwaddr[5] = macaddress[5]; - - /* maximum transfer unit */ - netif->mtu = 1500; - - /* device capabilities */ - /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ - netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; - - /* Enable MAC and DMA transmission and reception */ - HAL_ETH_Start(&EthHandle); -#if LWIP_IGMP - netif_set_igmp_mac_filter(netif, igmp_mac_filter); -#endif - /**** Configure PHY to generate an interrupt when Eth Link state changes ****/ - /* Read Register Configuration */ - HAL_ETH_ReadPHYRegister(&EthHandle, PHY_IMR, ®value); - - regvalue |= PHY_ISFR_INT4; - - /* Enable Interrupt on change of link status */ - HAL_ETH_WritePHYRegister(&EthHandle, PHY_IMR, regvalue ); -#if LWIP_IGMP - ETH_HashTableHigh=EthHandle.Instance->MACHTHR; - ETH_HashTableLow=EthHandle.Instance->MACHTLR; -#endif -} - -/** - * @brief This function should do the actual transmission of the packet. The packet is - * contained in the pbuf that is passed to the function. This pbuf - * might be chained. - * - * @param netif the lwip network interface structure for this ethernetif - * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) - * @return ERR_OK if the packet could be sent - * an err_t value if the packet couldn't be sent - * - * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to - * strange results. You might consider waiting for space in the DMA queue - * to become availale since the stack doesn't retry to send a packet - * dropped because of memory failure (except for the TCP timers). - */ -static err_t low_level_output(struct netif *netif, struct pbuf *p) -{ - err_t errval; - struct pbuf *q; - uint8_t *buffer = (uint8_t *)(EthHandle.TxDesc->Buffer1Addr); - __IO ETH_DMADescTypeDef *DmaTxDesc; - uint32_t framelength = 0; - uint32_t bufferoffset = 0; - uint32_t byteslefttocopy = 0; - uint32_t payloadoffset = 0; - - UNUSED(netif); - - DmaTxDesc = EthHandle.TxDesc; - bufferoffset = 0; - - /* copy frame from pbufs to driver buffers */ - for(q = p; q != NULL; q = q->next) - { - /* Is this buffer available? If not, goto error */ - if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) - { - errval = ERR_USE; - goto error; - } - - /* Get bytes in current lwIP buffer */ - byteslefttocopy = q->len; - payloadoffset = 0; - - /* Check if the length of data to copy is bigger than Tx buffer size*/ - while( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE ) - { - /* Copy data to Tx buffer*/ - memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset) ); - - /* Point to next descriptor */ - DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr); - - /* Check if the buffer is available */ - if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) - { - errval = ERR_USE; - goto error; - } - - buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr); - - byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset); - payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset); - framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset); - bufferoffset = 0; - } - - /* Copy the remaining bytes */ - memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), byteslefttocopy ); - bufferoffset = bufferoffset + byteslefttocopy; - framelength = framelength + byteslefttocopy; - } - - /* Prepare transmit descriptors to give to DMA */ - HAL_ETH_TransmitFrame(&EthHandle, framelength); - - errval = ERR_OK; - -error: - - /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */ - if ((EthHandle.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) - { - /* Clear TUS ETHERNET DMA flag */ - EthHandle.Instance->DMASR = ETH_DMASR_TUS; - - /* Resume DMA transmission*/ - EthHandle.Instance->DMATPDR = 0; - } - return errval; -} - -/** - * @brief Should allocate a pbuf and transfer the bytes of the incoming - * packet from the interface into the pbuf. - * - * @param netif the lwip network interface structure for this ethernetif - * @return a pbuf filled with the received packet (including MAC header) - * NULL on memory error - */ -static struct pbuf * low_level_input(struct netif *netif) -{ - struct pbuf *p = NULL; - struct pbuf *q; - uint16_t len; - uint8_t *buffer; - __IO ETH_DMADescTypeDef *dmarxdesc; - uint32_t bufferoffset = 0; - uint32_t payloadoffset = 0; - uint32_t byteslefttocopy = 0; - uint32_t i=0; - - UNUSED(netif); - - if (HAL_ETH_GetReceivedFrame_IT(&EthHandle) != HAL_OK) - return NULL; - - /* Obtain the size of the packet and put it into the "len" variable. */ - len = EthHandle.RxFrameInfos.length; - buffer = (uint8_t *)EthHandle.RxFrameInfos.buffer; - - if (len > 0) - { - /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */ - p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); - } - - if (p != NULL) - { - dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc; - bufferoffset = 0; - - for(q = p; q != NULL; q = q->next) - { - byteslefttocopy = q->len; - payloadoffset = 0; - - /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size */ - while( (byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE ) - { - /* Copy data to pbuf */ - memcpy( (uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset)); - - /* Point to next descriptor */ - dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr); - buffer = (uint8_t *)(dmarxdesc->Buffer1Addr); - - byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset); - payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset); - bufferoffset = 0; - } - - /* Copy remaining data in pbuf */ - memcpy( (uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), byteslefttocopy); - bufferoffset = bufferoffset + byteslefttocopy; - } - } - - /* Release descriptors to DMA */ - /* Point to first descriptor */ - dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc; - /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ - for (i=0; i< EthHandle.RxFrameInfos.SegCount; i++) - { - dmarxdesc->Status |= ETH_DMARXDESC_OWN; - dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr); - } - - /* Clear Segment_Count */ - EthHandle.RxFrameInfos.SegCount =0; - - /* When Rx Buffer unavailable flag is set: clear it and resume reception */ - if ((EthHandle.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) - { - /* Clear RBUS ETHERNET DMA flag */ - EthHandle.Instance->DMASR = ETH_DMASR_RBUS; - /* Resume DMA reception */ - EthHandle.Instance->DMARPDR = 0; - } - return p; -} - -/** - * @brief This function should be called when a packet is ready to be read - * from the interface. It uses the function low_level_input() that - * should handle the actual reception of bytes from the network - * interface. Then the type of the received packet is determined and - * the appropriate input function is called. - * - * @param netif the lwip network interface structure for this ethernetif - */ -void ethernetif_input(struct netif *netif) -{ - err_t err; - struct pbuf *p; - - /* move received packet into a new pbuf */ - p = low_level_input(netif); - - /* no packet could be read, silently ignore this */ - if (p == NULL) return; - - /* entry point to the LwIP stack */ - err = netif->input(p, netif); - - if (err != ERR_OK) - { - LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); - pbuf_free(p); - p = NULL; - } -} - -/** - * @brief Returns the current state - * - * @param None - * @return 0 not initialized else 1 - */ -uint8_t ethernetif_is_init(void) -{ - return (EthHandle.State != HAL_ETH_STATE_RESET); -} - -/** - * @brief Should be called at the beginning of the program to set up the - * network interface. It calls the function low_level_init() to do the - * actual setup of the hardware. - * - * This function should be passed as a parameter to netif_add(). - * - * @param netif the lwip network interface structure for this ethernetif - * @return ERR_OK if the loopif is initialized - * ERR_MEM if private data couldn't be allocated - * any other err_t on error - */ -err_t ethernetif_init(struct netif *netif) -{ - LWIP_ASSERT("netif != NULL", (netif != NULL)); - -#if LWIP_NETIF_HOSTNAME - /* Initialize interface hostname */ - netif->hostname = "lwip"; -#endif /* LWIP_NETIF_HOSTNAME */ - - netif->name[0] = IFNAME0; - netif->name[1] = IFNAME1; - /* We directly use etharp_output() here to save a function call. - * You can instead declare your own function an call etharp_output() - * from it if you have to do some checks before sending (e.g. if link - * is available...) */ - netif->output = etharp_output; - netif->linkoutput = low_level_output; - - /* initialize the hardware */ - low_level_init(netif); - - return ERR_OK; -} - -/** - * @brief Returns the current time in milliseconds - * when LWIP_TIMERS == 1 and NO_SYS == 1 - * @param None - * @retval Current Time value - */ -u32_t sys_now(void) -{ - return HAL_GetTick(); -} - -/** - * @brief This function sets the netif link status. - * @param netif: the network interface - * @retval None - */ -void ethernetif_set_link(struct netif *netif) -{ - uint32_t regvalue = 0; - - /* Read PHY_MISR*/ - HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ISFR, ®value); - - /* Check whether the link interrupt has occurred or not */ - if((regvalue & PHY_ISFR_INT4) != (uint16_t)RESET) - { - netif_set_link_down(netif); - } - - HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, ®value); - - if((regvalue & PHY_LINKED_STATUS) != (uint16_t)RESET) { -#if LWIP_IGMP - if (!(netif->flags & NETIF_FLAG_IGMP)) { - netif->flags |= NETIF_FLAG_IGMP; - igmp_init(); - igmp_start(netif); - } -#endif - netif_set_link_up(netif); - } -} - -/** - * @brief Link callback function, this function is called on change of link status - * to update low level driver configuration. - * @param netif: The network interface - * @retval None - */ -void ethernetif_update_config(struct netif *netif) -{ - __IO uint32_t tickstart = 0; - uint32_t regvalue = 0; - - if(netif_is_link_up(netif)) - { - /* Restart the auto-negotiation */ - if(EthHandle.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE) - { - /* Enable Auto-Negotiation */ - HAL_ETH_WritePHYRegister(&EthHandle, PHY_BCR, PHY_AUTONEGOTIATION); - - /* Get tick */ - tickstart = HAL_GetTick(); - - /* Wait until the auto-negotiation will be completed */ - do - { - HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, ®value); - - /* Check for the Timeout ( 1s ) */ - if((HAL_GetTick() - tickstart ) > 1000) - { - /* In case of timeout */ - goto error; - } - - } while (((regvalue & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE)); - - /* Read the result of the auto-negotiation */ - HAL_ETH_ReadPHYRegister(&EthHandle, PHY_SR, ®value); - - /* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */ - if((regvalue & PHY_DUPLEX_STATUS) != (uint32_t)RESET) - { - /* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */ - EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX; - } - else - { - /* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */ - EthHandle.Init.DuplexMode = ETH_MODE_HALFDUPLEX; - } - /* Configure the MAC with the speed fixed by the auto-negotiation process */ - if(regvalue & PHY_SPEED_STATUS) - { - /* Set Ethernet speed to 10M following the auto-negotiation */ - EthHandle.Init.Speed = ETH_SPEED_10M; - } - else - { - /* Set Ethernet speed to 100M following the auto-negotiation */ - EthHandle.Init.Speed = ETH_SPEED_100M; - } - } - else /* AutoNegotiation Disable */ - { - error : - /* Check parameters */ - assert_param(IS_ETH_SPEED(EthHandle.Init.Speed)); - assert_param(IS_ETH_DUPLEX_MODE(EthHandle.Init.DuplexMode)); - - /* Set MAC Speed and Duplex Mode to PHY */ - HAL_ETH_WritePHYRegister(&EthHandle, PHY_BCR, ((uint16_t)(EthHandle.Init.DuplexMode >> 3) | - (uint16_t)(EthHandle.Init.Speed >> 1))); - } - - /* ETHERNET MAC Re-Configuration */ - HAL_ETH_ConfigMAC(&EthHandle, (ETH_MACInitTypeDef *) NULL); - - /* Restart MAC interface */ - HAL_ETH_Start(&EthHandle); - } - else - { - /* Stop MAC interface */ - HAL_ETH_Stop(&EthHandle); - } - - ethernetif_notify_conn_changed(netif); -} - -/** - * @brief This function notify user about link status changement. - * @param netif: the network interface - * @retval None - */ -__weak void ethernetif_notify_conn_changed(struct netif *netif) -{ - /* NOTE : This is function clould be implemented in user file - when the callback is needed, - */ - UNUSED(netif); -} - -/** - * @brief This function set a custom MAC address. This function must be called - * before ethernetif_init(). - * @param mac: mac address - * @retval None - */ -void ethernetif_set_mac_addr(const uint8_t *mac) { - if(mac != NULL) { - memcpy(macaddress,mac,6); - } -} - -#if LWIP_IGMP -err_t igmp_mac_filter( struct netif *netif, const ip4_addr_t *ip4_addr, netif_mac_filter_action action ) -{ - uint8_t mac[6]; - const uint8_t *p = (const uint8_t *)ip4_addr; - - mac[0] = 0x01; - mac[1] = 0x00; - mac[2] = 0x5E; - mac[3] = *(p+1) & 0x7F; - mac[4] = *(p+2); - mac[5] = *(p+3); - - register_multicast_address(mac); - - return 0; -} - -#ifndef HASH_BITS -#define HASH_BITS 6 /* #bits in hash */ -#endif - -uint32_t ethcrc(const uint8_t *data, size_t length) -{ - uint32_t crc = 0xffffffff; - size_t i; - int j; - - for (i = 0; i < length; i++) { - for (j = 0; j < 8; j++) { - if (((crc >> 31) ^ (data[i] >> j)) & 0x01) { - /* x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 */ - crc = (crc << 1) ^ 0x04C11DB7; - } else { - crc = crc << 1; - } - } - } - return ~crc; -} - -void register_multicast_address(const uint8_t *mac) -{ - uint32_t crc; - uint8_t hash; - - /* Calculate crc32 value of mac address */ - crc = ethcrc(mac, HASH_BITS); - - /* - * Only upper HASH_BITS are used - * which point to specific bit in the hash registers - */ - hash = (crc >> 26) & 0x3F; - - if (hash > 31) { - ETH_HashTableHigh |= 1 << (hash - 32); - EthHandle.Instance->MACHTHR = ETH_HashTableHigh; - } else { - ETH_HashTableLow |= 1 << hash; - EthHandle.Instance->MACHTLR =ETH_HashTableLow; - } -} -#endif /* LWIP_IGMP */ - - -#ifdef ETH_INPUT_USE_IT -/** - * @brief Ethernet Rx Transfer completed callback - * @param heth: ETH handle - * @retval None - */ -void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) -{ - ethernetif_input(&gnetif); -} - -/** - * @brief This function handles Ethernet interrupt request. - * @param None - * @retval None - */ -void ETH_IRQHandler(void) -{ - HAL_ETH_IRQHandler(&EthHandle); -} -#endif /* ETH_INPUT_USE_IT */ - -#ifdef __cplusplus -} -#endif -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +/** + ****************************************************************************** + * @file ethernetif.c + * @author MCD Application Team & Wi6Labs + * @version V1.5.0 + * @date 20-june-2017 + * @brief This file implements Ethernet network interface drivers for lwIP + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2017 STMicroelectronics International N.V. + * All rights reserved.

+ * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "stm32_def.h" +#include "lwip/timeouts.h" +#include "netif/etharp.h" +#include "ethernetif.h" +#include +#include "PeripheralPins.h" +#include "lwip/igmp.h" +#include "stm32_eth.h" +#if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01050000) +#include "variant.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Network interface name */ +#define IFNAME0 's' +#define IFNAME1 't' + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma data_alignment=4 +#endif +__ALIGN_BEGIN ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __ALIGN_END;/* Ethernet Rx MA Descriptor */ + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma data_alignment=4 +#endif +__ALIGN_BEGIN ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] __ALIGN_END;/* Ethernet Tx DMA Descriptor */ + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma data_alignment=4 +#endif +__ALIGN_BEGIN uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __ALIGN_END; /* Ethernet Receive Buffer */ + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma data_alignment=4 +#endif +__ALIGN_BEGIN uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END; /* Ethernet Transmit Buffer */ + +static ETH_HandleTypeDef EthHandle; + +static uint8_t macaddress[6] = { MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5 }; + +#if LWIP_IGMP +uint32_t ETH_HashTableHigh = 0x0; +uint32_t ETH_HashTableLow = 0x0; +#endif + +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/******************************************************************************* + Ethernet MSP Routines +*******************************************************************************/ +/** + * @brief Initializes the ETH MSP. + * @param heth: ETH handle + * @retval None + */ +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + GPIO_InitTypeDef GPIO_InitStructure; + const PinMap *map = PinMap_Ethernet; + PinName pin = pin_pinName(map); + GPIO_TypeDef *port; + + UNUSED(heth); + + /* Ethernet pins configuration ************************************************/ + + if (map != NULL) { + while (pin != NC) { + /* Set port clock */ + port = set_GPIO_Port_Clock(STM_PORT(pin)); + + /* pin configuration */ + GPIO_InitStructure.Pin = STM_GPIO_PIN(pin); + GPIO_InitStructure.Mode = STM_PIN_MODE(pinmap_function(pin, PinMap_Ethernet)); + GPIO_InitStructure.Pull = STM_PIN_PUPD(pinmap_function(pin, PinMap_Ethernet)); + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStructure.Alternate = STM_PIN_AFNUM(pinmap_function(pin, PinMap_Ethernet)); + HAL_GPIO_Init(port, &GPIO_InitStructure); + + pin = pin_pinName(++map); + } + } + +#ifdef ETH_INPUT_USE_IT + /* Enable the Ethernet global Interrupt */ + HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); + HAL_NVIC_EnableIRQ(ETH_IRQn); +#endif /* ETH_INPUT_USE_IT */ + + /* Enable ETHERNET clock */ + __HAL_RCC_ETH_CLK_ENABLE(); +} + +/******************************************************************************* + LL Driver Interface ( LwIP stack --> ETH) +*******************************************************************************/ +/** + * @brief In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ +static void low_level_init(struct netif *netif) +{ + uint32_t regvalue; + + EthHandle.Instance = ETH; + EthHandle.Init.MACAddr = macaddress; + EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE; + EthHandle.Init.Speed = ETH_SPEED_100M; + EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX; +#ifdef ETHERNET_RMII_MODE_CONFIGURATION + EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII; +#else + EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII; +#endif /* ETHERNET_RMII_MODE_CONFIGURATION */ +#ifdef ETH_INPUT_USE_IT + EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE; +#else + EthHandle.Init.RxMode = ETH_RXPOLLING_MODE; +#endif /* ETH_INPUT_USE_IT */ + EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE; + EthHandle.Init.PhyAddress = LAN8742A_PHY_ADDRESS; + + /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */ + if (HAL_ETH_Init(&EthHandle) == HAL_OK) { + /* Set netif link flag */ + netif->flags |= NETIF_FLAG_LINK_UP; + } + + /* Initialize Tx Descriptors list: Chain Mode */ + HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); + + /* Initialize Rx Descriptors list: Chain Mode */ + HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); + + /* set MAC hardware address length */ + netif->hwaddr_len = ETH_HWADDR_LEN; + + /* set MAC hardware address */ + netif->hwaddr[0] = macaddress[0]; + netif->hwaddr[1] = macaddress[1]; + netif->hwaddr[2] = macaddress[2]; + netif->hwaddr[3] = macaddress[3]; + netif->hwaddr[4] = macaddress[4]; + netif->hwaddr[5] = macaddress[5]; + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + + /* Enable MAC and DMA transmission and reception */ + HAL_ETH_Start(&EthHandle); +#if LWIP_IGMP + netif_set_igmp_mac_filter(netif, igmp_mac_filter); +#endif + /**** Configure PHY to generate an interrupt when Eth Link state changes ****/ + /* Read Register Configuration */ + HAL_ETH_ReadPHYRegister(&EthHandle, PHY_IMR, ®value); + + regvalue |= PHY_ISFR_INT4; + + /* Enable Interrupt on change of link status */ + HAL_ETH_WritePHYRegister(&EthHandle, PHY_IMR, regvalue); +#if LWIP_IGMP + ETH_HashTableHigh = EthHandle.Instance->MACHTHR; + ETH_HashTableLow = EthHandle.Instance->MACHTLR; +#endif +} + +/** + * @brief This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become availale since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ +static err_t low_level_output(struct netif *netif, struct pbuf *p) +{ + err_t errval; + struct pbuf *q; + uint8_t *buffer = (uint8_t *)(EthHandle.TxDesc->Buffer1Addr); + __IO ETH_DMADescTypeDef *DmaTxDesc; + uint32_t framelength = 0; + uint32_t bufferoffset = 0; + uint32_t byteslefttocopy = 0; + uint32_t payloadoffset = 0; + + UNUSED(netif); + + DmaTxDesc = EthHandle.TxDesc; + bufferoffset = 0; + + /* copy frame from pbufs to driver buffers */ + for (q = p; q != NULL; q = q->next) { + /* Is this buffer available? If not, goto error */ + if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) { + errval = ERR_USE; + goto error; + } + + /* Get bytes in current lwIP buffer */ + byteslefttocopy = q->len; + payloadoffset = 0; + + /* Check if the length of data to copy is bigger than Tx buffer size*/ + while ((byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE) { + /* Copy data to Tx buffer*/ + memcpy((uint8_t *)((uint8_t *)buffer + bufferoffset), (uint8_t *)((uint8_t *)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset)); + + /* Point to next descriptor */ + DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr); + + /* Check if the buffer is available */ + if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) { + errval = ERR_USE; + goto error; + } + + buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr); + + byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset); + framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset); + bufferoffset = 0; + } + + /* Copy the remaining bytes */ + memcpy((uint8_t *)((uint8_t *)buffer + bufferoffset), (uint8_t *)((uint8_t *)q->payload + payloadoffset), byteslefttocopy); + bufferoffset = bufferoffset + byteslefttocopy; + framelength = framelength + byteslefttocopy; + } + + /* Prepare transmit descriptors to give to DMA */ + HAL_ETH_TransmitFrame(&EthHandle, framelength); + + errval = ERR_OK; + +error: + + /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */ + if ((EthHandle.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) { + /* Clear TUS ETHERNET DMA flag */ + EthHandle.Instance->DMASR = ETH_DMASR_TUS; + + /* Resume DMA transmission*/ + EthHandle.Instance->DMATPDR = 0; + } + return errval; +} + +/** + * @brief Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +static struct pbuf *low_level_input(struct netif *netif) +{ + struct pbuf *p = NULL; + struct pbuf *q; + uint16_t len; + uint8_t *buffer; + __IO ETH_DMADescTypeDef *dmarxdesc; + uint32_t bufferoffset = 0; + uint32_t payloadoffset = 0; + uint32_t byteslefttocopy = 0; + uint32_t i = 0; + + UNUSED(netif); + + if (HAL_ETH_GetReceivedFrame_IT(&EthHandle) != HAL_OK) { + return NULL; + } + + /* Obtain the size of the packet and put it into the "len" variable. */ + len = EthHandle.RxFrameInfos.length; + buffer = (uint8_t *)EthHandle.RxFrameInfos.buffer; + + if (len > 0) { + /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + } + + if (p != NULL) { + dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc; + bufferoffset = 0; + + for (q = p; q != NULL; q = q->next) { + byteslefttocopy = q->len; + payloadoffset = 0; + + /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size */ + while ((byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE) { + /* Copy data to pbuf */ + memcpy((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset)); + + /* Point to next descriptor */ + dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr); + buffer = (uint8_t *)(dmarxdesc->Buffer1Addr); + + byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset); + bufferoffset = 0; + } + + /* Copy remaining data in pbuf */ + memcpy((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), byteslefttocopy); + bufferoffset = bufferoffset + byteslefttocopy; + } + } + + /* Release descriptors to DMA */ + /* Point to first descriptor */ + dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc; + /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ + for (i = 0; i < EthHandle.RxFrameInfos.SegCount; i++) { + dmarxdesc->Status |= ETH_DMARXDESC_OWN; + dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr); + } + + /* Clear Segment_Count */ + EthHandle.RxFrameInfos.SegCount = 0; + + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((EthHandle.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) { + /* Clear RBUS ETHERNET DMA flag */ + EthHandle.Instance->DMASR = ETH_DMASR_RBUS; + /* Resume DMA reception */ + EthHandle.Instance->DMARPDR = 0; + } + return p; +} + +/** + * @brief This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +void ethernetif_input(struct netif *netif) +{ + err_t err; + struct pbuf *p; + + /* move received packet into a new pbuf */ + p = low_level_input(netif); + + /* no packet could be read, silently ignore this */ + if (p == NULL) { + return; + } + + /* entry point to the LwIP stack */ + err = netif->input(p, netif); + + if (err != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + p = NULL; + } +} + +/** + * @brief Returns the current state + * + * @param None + * @return 0 not initialized else 1 + */ +uint8_t ethernetif_is_init(void) +{ + return (EthHandle.State != HAL_ETH_STATE_RESET); +} + +/** + * @brief Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ + + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = etharp_output; + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} + +/** + * @brief Returns the current time in milliseconds + * when LWIP_TIMERS == 1 and NO_SYS == 1 + * @param None + * @retval Current Time value + */ +u32_t sys_now(void) +{ + return HAL_GetTick(); +} + +/** + * @brief This function sets the netif link status. + * @param netif: the network interface + * @retval None + */ +void ethernetif_set_link(struct netif *netif) +{ + uint32_t regvalue = 0; + + /* Read PHY_MISR*/ + HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ISFR, ®value); + + /* Check whether the link interrupt has occurred or not */ + if ((regvalue & PHY_ISFR_INT4) != (uint16_t)RESET) { + netif_set_link_down(netif); + } + + HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, ®value); + + if ((regvalue & PHY_LINKED_STATUS) != (uint16_t)RESET) { +#if LWIP_IGMP + if (!(netif->flags & NETIF_FLAG_IGMP)) { + netif->flags |= NETIF_FLAG_IGMP; + igmp_init(); + igmp_start(netif); + } +#endif + netif_set_link_up(netif); + } +} + +/** + * @brief Link callback function, this function is called on change of link status + * to update low level driver configuration. + * @param netif: The network interface + * @retval None + */ +void ethernetif_update_config(struct netif *netif) +{ + __IO uint32_t tickstart = 0; + uint32_t regvalue = 0; + + if (netif_is_link_up(netif)) { + /* Restart the auto-negotiation */ + if (EthHandle.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE) { + /* Enable Auto-Negotiation */ + HAL_ETH_WritePHYRegister(&EthHandle, PHY_BCR, PHY_AUTONEGOTIATION); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until the auto-negotiation will be completed */ + do { + HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, ®value); + + /* Check for the Timeout ( 1s ) */ + if ((HAL_GetTick() - tickstart) > 1000) { + /* In case of timeout */ + goto error; + } + + } while (((regvalue & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE)); + + /* Read the result of the auto-negotiation */ + HAL_ETH_ReadPHYRegister(&EthHandle, PHY_SR, ®value); + + /* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */ + if ((regvalue & PHY_DUPLEX_STATUS) != (uint32_t)RESET) { + /* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */ + EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX; + } else { + /* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */ + EthHandle.Init.DuplexMode = ETH_MODE_HALFDUPLEX; + } + /* Configure the MAC with the speed fixed by the auto-negotiation process */ + if (regvalue & PHY_SPEED_STATUS) { + /* Set Ethernet speed to 10M following the auto-negotiation */ + EthHandle.Init.Speed = ETH_SPEED_10M; + } else { + /* Set Ethernet speed to 100M following the auto-negotiation */ + EthHandle.Init.Speed = ETH_SPEED_100M; + } + } else { /* AutoNegotiation Disable */ +error : + /* Check parameters */ + assert_param(IS_ETH_SPEED(EthHandle.Init.Speed)); + assert_param(IS_ETH_DUPLEX_MODE(EthHandle.Init.DuplexMode)); + + /* Set MAC Speed and Duplex Mode to PHY */ + HAL_ETH_WritePHYRegister(&EthHandle, PHY_BCR, ((uint16_t)(EthHandle.Init.DuplexMode >> 3) | + (uint16_t)(EthHandle.Init.Speed >> 1))); + } + + /* ETHERNET MAC Re-Configuration */ + HAL_ETH_ConfigMAC(&EthHandle, (ETH_MACInitTypeDef *) NULL); + + /* Restart MAC interface */ + HAL_ETH_Start(&EthHandle); + } else { + /* Stop MAC interface */ + HAL_ETH_Stop(&EthHandle); + } + + ethernetif_notify_conn_changed(netif); +} + +/** + * @brief This function notify user about link status changement. + * @param netif: the network interface + * @retval None + */ +__weak void ethernetif_notify_conn_changed(struct netif *netif) +{ + /* NOTE : This is function clould be implemented in user file + when the callback is needed, + */ + UNUSED(netif); +} + +/** + * @brief This function set a custom MAC address. This function must be called + * before ethernetif_init(). + * @param mac: mac address + * @retval None + */ +void ethernetif_set_mac_addr(const uint8_t *mac) +{ + if (mac != NULL) { + memcpy(macaddress, mac, 6); + } +} + +#if LWIP_IGMP +err_t igmp_mac_filter(struct netif *netif, const ip4_addr_t *ip4_addr, netif_mac_filter_action action) +{ + uint8_t mac[6]; + const uint8_t *p = (const uint8_t *)ip4_addr; + + mac[0] = 0x01; + mac[1] = 0x00; + mac[2] = 0x5E; + mac[3] = *(p + 1) & 0x7F; + mac[4] = *(p + 2); + mac[5] = *(p + 3); + + register_multicast_address(mac); + + return 0; +} + +#ifndef HASH_BITS +#define HASH_BITS 6 /* #bits in hash */ +#endif + +uint32_t ethcrc(const uint8_t *data, size_t length) +{ + uint32_t crc = 0xffffffff; + size_t i; + int j; + + for (i = 0; i < length; i++) { + for (j = 0; j < 8; j++) { + if (((crc >> 31) ^ (data[i] >> j)) & 0x01) { + /* x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 */ + crc = (crc << 1) ^ 0x04C11DB7; + } else { + crc = crc << 1; + } + } + } + return ~crc; +} + +void register_multicast_address(const uint8_t *mac) +{ + uint32_t crc; + uint8_t hash; + + /* Calculate crc32 value of mac address */ + crc = ethcrc(mac, HASH_BITS); + + /* + * Only upper HASH_BITS are used + * which point to specific bit in the hash registers + */ + hash = (crc >> 26) & 0x3F; + + if (hash > 31) { + ETH_HashTableHigh |= 1 << (hash - 32); + EthHandle.Instance->MACHTHR = ETH_HashTableHigh; + } else { + ETH_HashTableLow |= 1 << hash; + EthHandle.Instance->MACHTLR = ETH_HashTableLow; + } +} +#endif /* LWIP_IGMP */ + + +#ifdef ETH_INPUT_USE_IT +/** + * @brief Ethernet Rx Transfer completed callback + * @param heth: ETH handle + * @retval None + */ +void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) +{ + ethernetif_input(&gnetif); +} + +/** + * @brief This function handles Ethernet interrupt request. + * @param None + * @retval None + */ +void ETH_IRQHandler(void) +{ + HAL_ETH_IRQHandler(&EthHandle); +} +#endif /* ETH_INPUT_USE_IT */ + +#ifdef __cplusplus +} +#endif +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/utility/ethernetif.h b/src/utility/ethernetif.h old mode 100755 new mode 100644 index b0976fb..bab073e --- a/src/utility/ethernetif.h +++ b/src/utility/ethernetif.h @@ -1,74 +1,74 @@ -/** - ****************************************************************************** - * @file ethernetif.h - * @author MCD Application Team & Wi6Labs - * @version V1.5.0 - * @date 20-June-2017 - * @brief Ethernet interface header file. - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2017 STMicroelectronics International N.V. - * All rights reserved.

- * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: - * - * 1. Redistribution of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. - * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -#ifndef __ETHERNETIF_H__ -#define __ETHERNETIF_H__ -#ifdef __cplusplus - extern "C" { -#endif -#include "lwip/err.h" -#include "lwip/netif.h" -/* Exported types ------------------------------------------------------------*/ -uint8_t ethernetif_is_init(void); -err_t ethernetif_init(struct netif *netif); -void ethernetif_input(struct netif *netif); -void ethernetif_set_link(struct netif *netif); -void ethernetif_update_config(struct netif *netif); -void ethernetif_notify_conn_changed(struct netif *netif); - -void ethernetif_set_mac_addr(const uint8_t *mac); - -#if LWIP_IGMP -err_t igmp_mac_filter( struct netif *netif, const ip4_addr_t *ip4_addr, netif_mac_filter_action action ); -void register_multicast_address(const uint8_t *mac); -#endif - -#ifdef __cplusplus -} -#endif - -#endif +/** + ****************************************************************************** + * @file ethernetif.h + * @author MCD Application Team & Wi6Labs + * @version V1.5.0 + * @date 20-June-2017 + * @brief Ethernet interface header file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2017 STMicroelectronics International N.V. + * All rights reserved.

+ * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +#ifndef __ETHERNETIF_H__ +#define __ETHERNETIF_H__ +#ifdef __cplusplus +extern "C" { +#endif +#include "lwip/err.h" +#include "lwip/netif.h" +/* Exported types ------------------------------------------------------------*/ +uint8_t ethernetif_is_init(void); +err_t ethernetif_init(struct netif *netif); +void ethernetif_input(struct netif *netif); +void ethernetif_set_link(struct netif *netif); +void ethernetif_update_config(struct netif *netif); +void ethernetif_notify_conn_changed(struct netif *netif); + +void ethernetif_set_mac_addr(const uint8_t *mac); + +#if LWIP_IGMP +err_t igmp_mac_filter(struct netif *netif, const ip4_addr_t *ip4_addr, netif_mac_filter_action action); +void register_multicast_address(const uint8_t *mac); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index c7210dd..79dedb6 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -117,13 +117,10 @@ static void Netif_Config(void) /* Registers the default network interface */ netif_set_default(&gnetif); - if (netif_is_link_up(&gnetif)) - { + if (netif_is_link_up(&gnetif)) { /* When the netif is fully configured this function must be called */ netif_set_up(&gnetif); - } - else - { + } else { /* When the netif link is down this function must be called */ netif_set_down(&gnetif); } @@ -188,42 +185,42 @@ void stm32_eth_init(const uint8_t *mac, const uint8_t *ip, const uint8_t *gw, co { static uint8_t initDone = 0; - if(!initDone) { + if (!initDone) { /* Initialize the LwIP stack */ lwip_init(); - if(mac != NULL) { + if (mac != NULL) { ethernetif_set_mac_addr(mac); } // else default value is used: MAC_ADDR0 ... MAC_ADDR5 - if(ip != NULL) { - IP_ADDR4(&(gconfig.ipaddr),ip[0],ip[1],ip[2],ip[3]); + if (ip != NULL) { + IP_ADDR4(&(gconfig.ipaddr), ip[0], ip[1], ip[2], ip[3]); } else { - #if LWIP_DHCP - ip_addr_set_zero_ip4(&(gconfig.ipaddr)); - #else - IP_ADDR4(&(gconfig.ipaddr),IP_ADDR0,IP_ADDR1,IP_ADDR2,IP_ADDR3); - #endif /* LWIP_DHCP */ +#if LWIP_DHCP + ip_addr_set_zero_ip4(&(gconfig.ipaddr)); +#else + IP_ADDR4(&(gconfig.ipaddr), IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); +#endif /* LWIP_DHCP */ } - if(gw != NULL) { - IP_ADDR4(&(gconfig.gw),gw[0],gw[1],gw[2],gw[3]); + if (gw != NULL) { + IP_ADDR4(&(gconfig.gw), gw[0], gw[1], gw[2], gw[3]); } else { - #if LWIP_DHCP - ip_addr_set_zero_ip4(&(gconfig.gw)); - #else - IP_ADDR4(&(gconfig.gw),GW_ADDR0,GW_ADDR1,GW_ADDR2,GW_ADDR3); - #endif /* LWIP_DHCP */ +#if LWIP_DHCP + ip_addr_set_zero_ip4(&(gconfig.gw)); +#else + IP_ADDR4(&(gconfig.gw), GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); +#endif /* LWIP_DHCP */ } - if(netmask != NULL) { - IP_ADDR4(&(gconfig.netmask),netmask[0],netmask[1],netmask[2],netmask[3]); + if (netmask != NULL) { + IP_ADDR4(&(gconfig.netmask), netmask[0], netmask[1], netmask[2], netmask[3]); } else { - #if LWIP_DHCP - ip_addr_set_zero_ip4(&(gconfig.netmask)); - #else - IP_ADDR4(&(gconfig.netmask),NETMASK_ADDR0,NETMASK_ADDR1,NETMASK_ADDR2,NETMASK_ADDR3); - #endif /* LWIP_DHCP */ +#if LWIP_DHCP + ip_addr_set_zero_ip4(&(gconfig.netmask)); +#else + IP_ADDR4(&(gconfig.netmask), NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); +#endif /* LWIP_DHCP */ } /* Configure the Network interface */ @@ -247,7 +244,8 @@ void stm32_eth_init(const uint8_t *mac, const uint8_t *ip, const uint8_t *gw, co * @param None * @retval 1 for initialized, 0 for not initialized */ -uint8_t stm32_eth_is_init(void) { +uint8_t stm32_eth_is_init(void) +{ return ethernetif_is_init(); } @@ -256,7 +254,8 @@ uint8_t stm32_eth_is_init(void) { * @param None * @retval 1 for link up, 0 for link down */ -uint8_t stm32_eth_link_up(void) { +uint8_t stm32_eth_link_up(void) +{ return netif_is_link_up(&gnetif); } @@ -265,7 +264,8 @@ uint8_t stm32_eth_link_up(void) { * @param None * @retval None */ -void stm32_eth_scheduler(void) { +void stm32_eth_scheduler(void) +{ /* Read a received packet from the Ethernet buffers and send it to the lwIP for handling */ #ifndef ETH_INPUT_USE_IT @@ -273,7 +273,7 @@ void stm32_eth_scheduler(void) { #endif /* ETH_INPUT_USE_IT */ /* Check ethernet link status */ - if((HAL_GetTick() - gEhtLinkTickStart) >= TIME_CHECK_ETH_LINK_STATE) { + if ((HAL_GetTick() - gEhtLinkTickStart) >= TIME_CHECK_ETH_LINK_STATE) { ethernetif_set_link(&gnetif); gEhtLinkTickStart = HAL_GetTick(); } @@ -293,7 +293,8 @@ void stm32_eth_scheduler(void) { * @param None * @retval true if DHCP enabled or false if not used */ -uint8_t stm32_dhcp_started(void) { +uint8_t stm32_dhcp_started(void) +{ return DHCP_Started_by_user; } @@ -302,63 +303,55 @@ uint8_t stm32_dhcp_started(void) { * @param netif pointer to generic data structure used for all lwIP network interfaces * @retval None */ -void stm32_DHCP_process(struct netif *netif) { +void stm32_DHCP_process(struct netif *netif) +{ struct dhcp *dhcp; - if(netif_is_link_up(netif)){ - switch (DHCP_state) - { - case DHCP_START: - { - ip_addr_set_zero_ip4(&netif->ip_addr); - ip_addr_set_zero_ip4(&netif->netmask); - ip_addr_set_zero_ip4(&netif->gw); - DHCP_state = DHCP_WAIT_ADDRESS; - dhcp_start(netif); - DHCP_Started_by_user = 1; - } - break; - - case DHCP_WAIT_ADDRESS: - { - if (dhcp_supplied_address(netif)) - { - DHCP_state = DHCP_ADDRESS_ASSIGNED; + if (netif_is_link_up(netif)) { + switch (DHCP_state) { + case DHCP_START: { + ip_addr_set_zero_ip4(&netif->ip_addr); + ip_addr_set_zero_ip4(&netif->netmask); + ip_addr_set_zero_ip4(&netif->gw); + DHCP_state = DHCP_WAIT_ADDRESS; + dhcp_start(netif); + DHCP_Started_by_user = 1; } - else - { - dhcp = (struct dhcp *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP); + break; + + case DHCP_WAIT_ADDRESS: { + if (dhcp_supplied_address(netif)) { + DHCP_state = DHCP_ADDRESS_ASSIGNED; + } else { + dhcp = (struct dhcp *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP); - /* DHCP timeout */ - if (dhcp->tries > MAX_DHCP_TRIES) - { - DHCP_state = DHCP_TIMEOUT; + /* DHCP timeout */ + if (dhcp->tries > MAX_DHCP_TRIES) { + DHCP_state = DHCP_TIMEOUT; - // If DHCP address not bind, keep DHCP stopped - DHCP_Started_by_user = 0; + // If DHCP address not bind, keep DHCP stopped + DHCP_Started_by_user = 0; - /* Stop DHCP */ - dhcp_stop(netif); + /* Stop DHCP */ + dhcp_stop(netif); + } } } - } - break; - case DHCP_ASK_RELEASE: - { - /* Force release */ - dhcp_release(netif); - dhcp_stop(netif); - DHCP_state = DHCP_OFF; - } - break; - case DHCP_LINK_DOWN: - { - /* Stop DHCP */ - dhcp_stop(netif); - DHCP_state = DHCP_OFF; - } - break; - default: break; + break; + case DHCP_ASK_RELEASE: { + /* Force release */ + dhcp_release(netif); + dhcp_stop(netif); + DHCP_state = DHCP_OFF; + } + break; + case DHCP_LINK_DOWN: { + /* Stop DHCP */ + dhcp_stop(netif); + DHCP_state = DHCP_OFF; + } + break; + default: break; } } else { DHCP_state = DHCP_OFF; @@ -373,8 +366,7 @@ void stm32_DHCP_process(struct netif *netif) { void stm32_DHCP_Periodic_Handle(struct netif *netif) { /* Fine DHCP periodic process every 500ms */ - if (HAL_GetTick() - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS) - { + if (HAL_GetTick() - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS) { DHCPfineTimer = HAL_GetTick(); /* process DHCP state machine */ stm32_DHCP_process(netif); @@ -386,7 +378,8 @@ void stm32_DHCP_Periodic_Handle(struct netif *netif) * @param None * @retval None */ -void stm32_DHCP_manual_config(void) { +void stm32_DHCP_manual_config(void) +{ dhcp_inform(&gnetif); } @@ -395,13 +388,14 @@ void stm32_DHCP_manual_config(void) { * @param None * @retval Renew or rebind. Adapted from Arduino Ethernet library. */ -uint8_t stm32_get_DHCP_lease_state(void) { +uint8_t stm32_get_DHCP_lease_state(void) +{ uint8_t res = 0; - struct dhcp* dhcp = (struct dhcp *)netif_get_client_data(&gnetif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP); + struct dhcp *dhcp = (struct dhcp *)netif_get_client_data(&gnetif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP); - if(dhcp->state == DHCP_STATE_RENEWING) { + if (dhcp->state == DHCP_STATE_RENEWING) { res = 2; - } else if(dhcp->state == DHCP_STATE_REBINDING) { + } else if (dhcp->state == DHCP_STATE_REBINDING) { res = 4; } @@ -413,7 +407,8 @@ uint8_t stm32_get_DHCP_lease_state(void) { * @param state: DHCP_START, DHCP_ASK_RELEASE or DHCP_STOP. Others should not be used. * @retval None */ -void stm32_set_DHCP_state(uint8_t state) { +void stm32_set_DHCP_state(uint8_t state) +{ DHCP_state = state; } @@ -429,7 +424,8 @@ void stm32_set_DHCP_state(uint8_t state) { DHCP_LINK_DOWN DHCP_ASK_RELEASE */ -uint8_t stm32_get_DHCP_state(void) { +uint8_t stm32_get_DHCP_state(void) +{ return DHCP_state; } @@ -440,7 +436,8 @@ uint8_t stm32_get_DHCP_state(void) { * @param None * @retval address in uint32_t format */ -uint32_t stm32_eth_get_ipaddr(void) { +uint32_t stm32_eth_get_ipaddr(void) +{ return ip4_addr_get_u32(&(gnetif.ip_addr)); } @@ -449,7 +446,8 @@ uint32_t stm32_eth_get_ipaddr(void) { * @param None * @retval address in uint32_t format */ -uint32_t stm32_eth_get_gwaddr(void) { +uint32_t stm32_eth_get_gwaddr(void) +{ return ip4_addr_get_u32(&(gnetif.gw)); } @@ -458,7 +456,8 @@ uint32_t stm32_eth_get_gwaddr(void) { * @param None * @retval address in uint32_t format */ -uint32_t stm32_eth_get_netmaskaddr(void) { +uint32_t stm32_eth_get_netmaskaddr(void) +{ return ip4_addr_get_u32(&(gnetif.netmask)); } @@ -467,7 +466,8 @@ uint32_t stm32_eth_get_netmaskaddr(void) { * @param None * @retval address in uint32_t format */ -uint32_t stm32_eth_get_dnsaddr(void) { +uint32_t stm32_eth_get_dnsaddr(void) +{ const ip_addr_t *tmp = dns_getserver(0); return ip4_addr_get_u32(tmp); } @@ -477,7 +477,8 @@ uint32_t stm32_eth_get_dnsaddr(void) { * @param None * @retval address in uint32_t format */ -uint32_t stm32_eth_get_dhcpaddr(void) { +uint32_t stm32_eth_get_dhcpaddr(void) +{ struct dhcp *dhcp = (struct dhcp *)netif_get_client_data(&gnetif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP); return ip4_addr_get_u32(&(dhcp->server_ip_addr)); } @@ -491,20 +492,17 @@ uint32_t stm32_eth_get_dhcpaddr(void) { */ void ethernetif_notify_conn_changed(struct netif *netif) { - if(netif_is_link_up(netif)) - { + if (netif_is_link_up(netif)) { /* Update DHCP state machine if DHCP used */ - if(DHCP_Started_by_user == 1) { + if (DHCP_Started_by_user == 1) { DHCP_state = DHCP_START; } /* When the netif is fully configured this function must be called.*/ netif_set_up(netif); - } - else - { + } else { /* Update DHCP state machine if DHCP used */ - if(DHCP_Started_by_user == 1) { + if (DHCP_Started_by_user == 1) { DHCP_state = DHCP_LINK_DOWN; } @@ -522,14 +520,11 @@ void ethernetif_notify_conn_changed(struct netif *netif) */ void User_notification(struct netif *netif) { - if (netif_is_up(netif)) - { + if (netif_is_up(netif)) { //Link up - } - else - { + } else { /* Update DHCP state machine */ - if(DHCP_Started_by_user == 1) { + if (DHCP_Started_by_user == 1) { DHCP_state = DHCP_LINK_DOWN; } } @@ -547,9 +542,9 @@ void stm32_dns_init(const uint8_t *dnsaddr) ip_addr_t ip; /* DNS initialized by DHCP when call dhcp_start() */ - if(!stm32_dhcp_started()) { + if (!stm32_dhcp_started()) { dns_init(); - IP_ADDR4(&ip,dnsaddr[0],dnsaddr[1],dnsaddr[2],dnsaddr[3]); + IP_ADDR4(&ip, dnsaddr[0], dnsaddr[1], dnsaddr[2], dnsaddr[3]); dns_setserver(0, &ip); } } @@ -565,7 +560,7 @@ void dns_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) { UNUSED(name); - if(ipaddr != NULL) { + if (ipaddr != NULL) { *((uint32_t *)callback_arg) = ip4_addr_get_u32(ipaddr); } else { *((uint32_t *)callback_arg) = 0; @@ -589,38 +584,38 @@ int8_t stm32_dns_gethostbyname(const char *hostname, uint32_t *ipaddr) *ipaddr = 0; err = dns_gethostbyname(hostname, &iphost, &dns_callback, ipaddr); - switch(err) { + switch (err) { case ERR_OK: *ipaddr = ip4_addr_get_u32(&iphost); ret = 1; - break; + break; case ERR_INPROGRESS: tickstart = HAL_GetTick(); - while(*ipaddr == 0) { + while (*ipaddr == 0) { stm32_eth_scheduler(); - if((HAL_GetTick() - tickstart) >= TIMEOUT_DNS_REQUEST) { + if ((HAL_GetTick() - tickstart) >= TIMEOUT_DNS_REQUEST) { ret = -1; break; } } - if(ret == 0) { - if(*ipaddr == 0) { + if (ret == 0) { + if (*ipaddr == 0) { ret = -2; } else { ret = 1; } } - break; + break; case ERR_ARG: ret = -4; - break; + break; default: ret = -4; - break; + break; } return ret; @@ -636,7 +631,7 @@ int8_t stm32_dns_gethostbyname(const char *hostname, uint32_t *ipaddr) */ ip_addr_t *u8_to_ip_addr(uint8_t *ipu8, ip_addr_t *ipaddr) { - IP_ADDR4(ipaddr,ipu8[0],ipu8[1],ipu8[2],ipu8[3]); + IP_ADDR4(ipaddr, ipu8[0], ipu8[1], ipu8[2], ipu8[3]); return ipaddr; } @@ -660,12 +655,12 @@ uint32_t ip_addr_to_u32(ip_addr_t *ipaddr) struct pbuf *stm32_new_data(struct pbuf *p, const uint8_t *buffer, size_t size) { // Allocate memory if pbuf doesn't exit yet. - if(p == NULL) { + if (p == NULL) { p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); - if(p != NULL) { + if (p != NULL) { // Copy data inside pbuf - if(ERR_OK == pbuf_take(p, (uint8_t *)buffer, size)) { + if (ERR_OK == pbuf_take(p, (uint8_t *)buffer, size)) { return p; } else { pbuf_free(p); @@ -677,9 +672,9 @@ struct pbuf *stm32_new_data(struct pbuf *p, const uint8_t *buffer, size_t size) else { struct pbuf *q = pbuf_alloc(PBUF_TRANSPORT, size + p->tot_len, PBUF_RAM); - if(q != NULL) { - if(ERR_OK == pbuf_copy(q, p)) { - if(ERR_OK == pbuf_take_at(q, (uint8_t *)buffer, size, p->tot_len)) { + if (q != NULL) { + if (ERR_OK == pbuf_copy(q, p)) { + if (ERR_OK == pbuf_take_at(q, (uint8_t *)buffer, size, p->tot_len)) { pbuf_free(p); p = q; return p; @@ -702,10 +697,10 @@ struct pbuf *stm32_free_data(struct pbuf *p) { uint16_t n; - if(p != NULL) { + if (p != NULL) { do { n = pbuf_free(p); - } while(n == 0); + } while (n == 0); } return NULL; @@ -724,31 +719,31 @@ uint16_t stm32_get_data(struct pbuf_data *data, uint8_t *buffer, size_t size) uint16_t i; uint16_t offset; uint16_t nb; - struct pbuf * ptr; + struct pbuf *ptr; - if((data->p == NULL) || (buffer == NULL) || (size == 0) || + if ((data->p == NULL) || (buffer == NULL) || (size == 0) || (data->available == 0) || (data->available > data->p->tot_len)) { return 0; } nb = 0; - while((nb < size) && (data->p != NULL) && (data->available > 0)) { + while ((nb < size) && (data->p != NULL) && (data->available > 0)) { ptr = data->p; offset = ptr->tot_len - data->available; /* Get data from p */ - for(i = 0; (nb < size) && ((offset + i) < ptr->len) && (data->available > 0); i++) { + for (i = 0; (nb < size) && ((offset + i) < ptr->len) && (data->available > 0); i++) { buffer[nb] = pbuf_get_at(ptr, offset + i); nb++; data->available--; } - if(nb < size) { + if (nb < size) { /* continue with next pbuf in chain (if any) */ data->p = ptr->next; - if(data->p != NULL) { + if (data->p != NULL) { /* increment reference count for p */ pbuf_ref(data->p); } @@ -758,7 +753,7 @@ uint16_t stm32_get_data(struct pbuf_data *data, uint8_t *buffer, size_t size) } } - if(data->available == 0) { + if (data->available == 0) { data->p = stm32_free_data(data->p); } @@ -783,9 +778,9 @@ void udp_receive_callback(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct udp_struct *udp_arg = (struct udp_struct *)arg; /* Send data to the application layer */ - if((udp_arg != NULL) && (udp_arg->pcb == pcb)) { + if ((udp_arg != NULL) && (udp_arg->pcb == pcb)) { // Free the old p buffer if not read - if(udp_arg->data.p != NULL) { + if (udp_arg->data.p != NULL) { pbuf_free(udp_arg->data.p); } @@ -795,7 +790,7 @@ void udp_receive_callback(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_copy(udp_arg->ip, *addr); udp_arg->port = port; - if(udp_arg->onDataArrival != NULL){ + if (udp_arg->onDataArrival != NULL) { udp_arg->onDataArrival(); } } else { @@ -818,10 +813,8 @@ err_t tcp_connected_callback(void *arg, struct tcp_pcb *tpcb, err_t err) { struct tcp_struct *tcp_arg = (struct tcp_struct *)arg; - if (err == ERR_OK) - { - if ((tcp_arg != NULL) && (tcp_arg->pcb == tpcb)) - { + if (err == ERR_OK) { + if ((tcp_arg != NULL) && (tcp_arg->pcb == tpcb)) { tcp_arg->state = TCP_CONNECTED; /* initialize LwIP tcp_recv callback function */ @@ -834,17 +827,13 @@ err_t tcp_connected_callback(void *arg, struct tcp_pcb *tpcb, err_t err) tcp_err(tpcb, tcp_err_callback); return ERR_OK; - } - else - { + } else { /* close connection */ tcp_connection_close(tpcb, tcp_arg); return ERR_ARG; } - } - else - { + } else { /* close connection */ tcp_connection_close(tpcb, tcp_arg); } @@ -867,26 +856,25 @@ err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err) /* set priority for the newly accepted tcp connection newpcb */ tcp_setprio(newpcb, TCP_PRIO_MIN); - if((tcpClient != NULL) && (ERR_OK == err)) { + if ((tcpClient != NULL) && (ERR_OK == err)) { struct tcp_struct *client = (struct tcp_struct *)mem_malloc(sizeof(struct tcp_struct)); - if (client != NULL) - { + if (client != NULL) { client->state = TCP_ACCEPTED; client->pcb = newpcb; client->data.p = NULL; client->data.available = 0; /* Looking for an empty soket */ - for(uint16_t i = 0; i < MAX_CLIENT; i++) { - if(tcpClient[i] == NULL) { + for (uint16_t i = 0; i < MAX_CLIENT; i++) { + if (tcpClient[i] == NULL) { tcpClient[i] = client; accepted = 1; break; } } - if(accepted) { + if (accepted) { /* pass newly allocated client structure as argument to newpcb */ tcp_arg(newpcb, client); @@ -908,9 +896,7 @@ err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err) /* return memory error */ ret_err = ERR_MEM; } - } - else - { + } else { /* close tcp connection */ tcp_connection_close(newpcb, client); mem_free(client); @@ -938,31 +924,25 @@ static err_t tcp_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t ret_err; /* if we receive an empty tcp frame from server => close connection */ - if (p == NULL) - { + if (p == NULL) { /* we're done sending, close connection */ tcp_connection_close(tpcb, tcp_arg); ret_err = ERR_OK; } /* else : a non empty frame was received from echo server but for some reason err != ERR_OK */ - else if(err != ERR_OK) - { + else if (err != ERR_OK) { /* free received pbuf*/ - if (p != NULL) - { + if (p != NULL) { pbuf_free(p); } ret_err = err; - } - else if((tcp_arg->state == TCP_CONNECTED) || (tcp_arg->state == TCP_ACCEPTED)) - { + } else if ((tcp_arg->state == TCP_CONNECTED) || (tcp_arg->state == TCP_ACCEPTED)) { /* Acknowledge data reception */ tcp_recved(tpcb, p->tot_len); - if(tcp_arg->data.p == NULL) { + if (tcp_arg->data.p == NULL) { tcp_arg->data.p = p; - } - else { + } else { pbuf_chain(tcp_arg->data.p, p); } @@ -970,8 +950,7 @@ static err_t tcp_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, ret_err = ERR_OK; } /* data received when connection already closed */ - else - { + else { /* Acknowledge data reception */ tcp_recved(tpcb, p->tot_len); @@ -996,8 +975,7 @@ static err_t tcp_sent_callback(void *arg, struct tcp_pcb *tpcb, u16_t len) LWIP_UNUSED_ARG(len); - if((tcp_arg != NULL) && (tcp_arg->pcb == tpcb)) - { + if ((tcp_arg != NULL) && (tcp_arg->pcb == tpcb)) { return ERR_OK; } @@ -1018,8 +996,8 @@ static void tcp_err_callback(void *arg, err_t err) { struct tcp_struct *tcp_arg = (struct tcp_struct *)arg; - if(tcp_arg != NULL) { - if(ERR_OK != err) { + if (tcp_arg != NULL) { + if (ERR_OK != err) { tcp_arg->pcb = NULL; tcp_arg->state = TCP_CLOSING; } @@ -1037,7 +1015,7 @@ void tcp_connection_close(struct tcp_pcb *tpcb, struct tcp_struct *tcp) /* remove callbacks */ tcp_recv(tpcb, NULL); tcp_sent(tpcb, NULL); - tcp_poll(tpcb, NULL,0); + tcp_poll(tpcb, NULL, 0); tcp_err(tpcb, NULL); tcp_accept(tpcb, NULL); diff --git a/src/utility/stm32_eth.h b/src/utility/stm32_eth.h index fd1cad6..4866be6 100644 --- a/src/utility/stm32_eth.h +++ b/src/utility/stm32_eth.h @@ -49,15 +49,14 @@ /* Exported types ------------------------------------------------------------*/ /* TCP connection state */ -typedef enum -{ +typedef enum { TCP_NONE = 0, TCP_CONNECTED, TCP_RECEIVED, TCP_SENT, TCP_ACCEPTED, TCP_CLOSING, -}tcp_client_states; +} tcp_client_states; /* Struct to store received data */ struct pbuf_data { From ece000225584039fde0e7e8714a4c4574072ee4f Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Mon, 24 Feb 2020 14:24:53 +0100 Subject: [PATCH 22/58] [CI] Add Continuous Integration workflow Signed-off-by: Frederic Pillon --- .github/workflows/Continuous-Integration.yml | 62 ++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/workflows/Continuous-Integration.yml diff --git a/.github/workflows/Continuous-Integration.yml b/.github/workflows/Continuous-Integration.yml new file mode 100644 index 0000000..982a286 --- /dev/null +++ b/.github/workflows/Continuous-Integration.yml @@ -0,0 +1,62 @@ +name: STM32Ethernet Continuous Integration +on: + push: + branches: + - master + paths-ignore: + - '*' + - '**.md' + - '**.txt' + pull_request: + paths-ignore: + - '*' + - '**.md' + - '**.txt' +jobs: + astyle_check: + runs-on: ubuntu-latest + name: AStyle check + steps: + # First of all, clone the repo using the checkout action. + - name: Checkout + uses: actions/checkout@master + + - name: Astyle check + id: Astyle + uses: stm32duino/actions/astyle-check@master + + # Use the output from the `Astyle` step + - name: Astyle Errors + if: failure() + run: | + cat ${{ steps.Astyle.outputs.astyle-result }} + exit 1 + spell-check: + runs-on: ubuntu-latest + name: Spell check + steps: + - uses: actions/checkout@master + - uses: arduino/actions/libraries/spell-check@master + # with: + # ignore-words-list: "./extras/codespell-ignore-words-list.txt" + lib_build: + runs-on: ubuntu-latest + name: Library compilation + steps: + # First of all, clone the repo using the checkout action. + - name: Checkout + uses: actions/checkout@master + + - name: Compilation + id: Compile + uses: stm32duino/actions/compile-examples@master + with: + board-pattern: "DISCO_F746NG|NUCLEO_F429ZI|NUCLEO_F767ZI" + libraries: "STM32duino LwIP" + + # Use the output from the `Compile` step + - name: Compilation Errors + if: failure() + run: | + cat ${{ steps.Compile.outputs.compile-result }} + exit 1 \ No newline at end of file From 81b18159715466f1a97082db4150e3e9a0fab0d0 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Mon, 24 Feb 2020 15:06:28 +0100 Subject: [PATCH 23/58] Fix typos Thanks codespell Signed-off-by: Frederic Pillon --- examples/AdvancedChatServer/AdvancedChatServer.ino | 2 +- .../BarometricPressureWebServer.ino | 2 +- examples/WebClient/WebClient.ino | 2 +- src/utility/ethernetif.cpp | 2 +- src/utility/stm32_eth.cpp | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/AdvancedChatServer/AdvancedChatServer.ino b/examples/AdvancedChatServer/AdvancedChatServer.ino index cdb236a..451e9a9 100644 --- a/examples/AdvancedChatServer/AdvancedChatServer.ino +++ b/examples/AdvancedChatServer/AdvancedChatServer.ino @@ -103,7 +103,7 @@ void loop() { } for (byte i = 0; i < 4; i++) { if (!(clients[i].connected())) { - // client.stop() invalidates the internal socket-descriptor, so next use of == will allways return false; + // client.stop() invalidates the internal socket-descriptor, so next use of == will always return false; clients[i].stop(); } } diff --git a/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino b/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino index 666f527..13d06bc 100644 --- a/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino +++ b/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino @@ -62,7 +62,7 @@ void setup() { Ethernet.begin(ip); server.begin(); - // initalize the data ready and chip select pins: + // initialize the data ready and chip select pins: pinMode(dataReadyPin, INPUT); pinMode(chipSelectPin, OUTPUT); diff --git a/examples/WebClient/WebClient.ino b/examples/WebClient/WebClient.ino index 35c9d7b..3592889 100644 --- a/examples/WebClient/WebClient.ino +++ b/examples/WebClient/WebClient.ino @@ -42,7 +42,7 @@ void setup() { // start the Ethernet connection: if (Ethernet.begin() == 0) { Serial.println("Failed to configure Ethernet using DHCP"); - // try to congifure using IP address instead of DHCP: + // try to configure using IP address instead of DHCP: Ethernet.begin(ip); } // give the Ethernet shield a second to initialize: diff --git a/src/utility/ethernetif.cpp b/src/utility/ethernetif.cpp index 346a0ad..e6bb1ae 100644 --- a/src/utility/ethernetif.cpp +++ b/src/utility/ethernetif.cpp @@ -239,7 +239,7 @@ static void low_level_init(struct netif *netif) * * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to * strange results. You might consider waiting for space in the DMA queue - * to become availale since the stack doesn't retry to send a packet + * to become available since the stack doesn't retry to send a packet * dropped because of memory failure (except for the TCP timers). */ static err_t low_level_output(struct netif *netif, struct pbuf *p) diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index 79dedb6..509d0c4 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -514,7 +514,7 @@ void ethernetif_notify_conn_changed(struct netif *netif) #endif /* LWIP_NETIF_LINK_CALLBACK */ /** - * @brief Notify the User about the nework interface config status + * @brief Notify the User about the network interface config status * @param netif: the network interface * @retval None */ @@ -805,7 +805,7 @@ void udp_receive_callback(void *arg, struct udp_pcb *pcb, struct pbuf *p, /** * @brief Function called when TCP connection established * @param arg: user supplied argument - * @param tpcb: pointer on the connection contol block + * @param tpcb: pointer on the connection control block * @param err: when connection correctly established err should be ERR_OK * @retval err_t: returned error */ @@ -865,7 +865,7 @@ err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err) client->data.p = NULL; client->data.available = 0; - /* Looking for an empty soket */ + /* Looking for an empty socket */ for (uint16_t i = 0; i < MAX_CLIENT; i++) { if (tcpClient[i] == NULL) { tcpClient[i] = client; @@ -916,7 +916,7 @@ err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err) * @param arg: argument to be passed to receive callback * @param tpcb: tcp connection control block * @param err: receive error code - * @retval err_t: retuned error + * @retval err_t: returned error */ static err_t tcp_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { From d14d8e89a90360088af095b5b2e1f7e46290bd0f Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Mon, 24 Feb 2020 16:47:24 +0100 Subject: [PATCH 24/58] Update library.properties --- library.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 2ad82c6..0c9c37a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino STM32Ethernet -version=1.0.5 +version=1.1.0 author=Various maintainer=STMicroelectronics sentence=Enables network connection (local and Internet) using the STM32 Board. @@ -7,4 +7,4 @@ paragraph=With this library you can use the STM32 board to connect to Internet. category=Communication url=https://github.com/stm32duino/STM32Ethernet architectures=stm32 -depends=STM32duino LwIP \ No newline at end of file +depends=STM32duino LwIP From 0d7e4dd535aecb86f3156ce1f3be65c0611e5b53 Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Wed, 11 Mar 2020 16:05:04 +0100 Subject: [PATCH 25/58] Added functionality to pass custom parameter to HardwareTimer callback Change prototype of callback function --- src/utility/stm32_eth.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index 509d0c4..28ad2ba 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -138,11 +138,15 @@ static void Netif_Config(void) */ #if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100) static void scheduler_callback(stimer_t *htim) -#else +#elif (STM32_CORE_VERSION <= 0x01080000) static void scheduler_callback(HardwareTimer *htim) +#else +static void scheduler_callback(void) #endif { +#if (STM32_CORE_VERSION <= 0x01080000) UNUSED(htim); +#endif stm32_eth_scheduler(); } From 6dd579b3d38d6ddb7b405bcfb46bbbad53476ac8 Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Fri, 13 Mar 2020 12:01:49 +0100 Subject: [PATCH 26/58] Rework ethernet cable hotplug detection Mimic NUCLEO-H743ZI Cube Application: LwIP_HTTP_Server_Netconn_RTOS Fixes #42 --- src/utility/ethernetif.cpp | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/utility/ethernetif.cpp b/src/utility/ethernetif.cpp index e6bb1ae..31aa806 100644 --- a/src/utility/ethernetif.cpp +++ b/src/utility/ethernetif.cpp @@ -67,6 +67,11 @@ extern "C" { #define IFNAME0 's' #define IFNAME1 't' +/* Definition of PHY SPECIAL CONTROL/STATUS REGISTER bitfield Auto-negotiation done indication */ +/* Placed in STM32Ethernet library instead of HAL conf to avoid compatibility dependence with Arduino_Core_STM32 */ +/* Could be moved from this file once Generic PHY is implemented */ +#define PHY_SR_AUTODONE ((uint16_t)0x1000) + /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ #if defined ( __ICCARM__ ) /*!< IAR Compiler */ @@ -530,32 +535,17 @@ void ethernetif_set_link(struct netif *netif) */ void ethernetif_update_config(struct netif *netif) { - __IO uint32_t tickstart = 0; uint32_t regvalue = 0; if (netif_is_link_up(netif)) { /* Restart the auto-negotiation */ if (EthHandle.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE) { - /* Enable Auto-Negotiation */ - HAL_ETH_WritePHYRegister(&EthHandle, PHY_BCR, PHY_AUTONEGOTIATION); - - /* Get tick */ - tickstart = HAL_GetTick(); - - /* Wait until the auto-negotiation will be completed */ - do { - HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, ®value); - - /* Check for the Timeout ( 1s ) */ - if ((HAL_GetTick() - tickstart) > 1000) { - /* In case of timeout */ - goto error; - } - } while (((regvalue & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE)); - - /* Read the result of the auto-negotiation */ + /* Check Auto negotiation */ HAL_ETH_ReadPHYRegister(&EthHandle, PHY_SR, ®value); + if ((regvalue & PHY_SR_AUTODONE) != PHY_SR_AUTODONE) { + goto error; + } /* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */ if ((regvalue & PHY_DUPLEX_STATUS) != (uint32_t)RESET) { From e07dd8d04de36a31dc002430bd245a5951787dd8 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 22 May 2020 09:13:44 +0200 Subject: [PATCH 27/58] Update library.properties --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 0c9c37a..da4cf0a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino STM32Ethernet -version=1.1.0 +version=1.2.0 author=Various maintainer=STMicroelectronics sentence=Enables network connection (local and Internet) using the STM32 Board. From 7907e3123654641dacaae6cd56ad1240e7544abb Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 22 May 2020 09:14:24 +0200 Subject: [PATCH 28/58] Update library.json --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index b93a2b7..d6b7529 100755 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/stm32duino/STM32Ethernet" }, - "version": "1.0.5", + "version": "1.2.0", "frameworks": "arduino", "platforms": "ststm32", "build": { From 4984100f485fb3a3d5f9ea28fc1fa0dd289e05f7 Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Thu, 3 Dec 2020 09:07:27 +0100 Subject: [PATCH 29/58] HardwareTimer: remove usage of TIMER_OUTPUT_COMPARE mode With introduction of PR https://github.com/stm32duino/Arduino_Core_STM32/pull/1247 Usage of TIMER_OUTPUT_COMPARE becomes obsolete. Note: removing setMode(1, TIMER_OUTPUT_COMPARE) also works before PR #1247. Signed-off-by: Alexandre Bourdiol --- src/utility/stm32_eth.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index 28ad2ba..22b3fa7 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -176,7 +176,6 @@ static void TIM_scheduler_Config(void) { /* Configure HardwareTimer */ HardwareTimer *EthTim = new HardwareTimer(DEFAULT_ETHERNET_TIMER); - EthTim->setMode(1, TIMER_OUTPUT_COMPARE); /* Timer set to 1ms */ EthTim->setOverflow(1000, MICROSEC_FORMAT); From ea18d121f02db38899a01aec32a9c87944ded073 Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Thu, 3 Dec 2020 09:46:17 +0100 Subject: [PATCH 30/58] Run astyle Fix astyle issue Signed-off-by: Alexandre Bourdiol --- src/lwipopts.h | 10 +++---- src/lwipopts_default.h | 56 +++++++++++++++++++------------------- src/utility/ethernetif.cpp | 2 +- src/utility/stm32_eth.cpp | 14 +++++----- src/utility/stm32_eth.h | 32 +++++++++++----------- 5 files changed, 57 insertions(+), 57 deletions(-) diff --git a/src/lwipopts.h b/src/lwipopts.h index 09bcbde..0cf3278 100644 --- a/src/lwipopts.h +++ b/src/lwipopts.h @@ -9,12 +9,12 @@ /* LwIP specific configuration options. */ #if __has_include("STM32lwipopts.h") -#include "STM32lwipopts.h" + #include "STM32lwipopts.h" #else -#if __has_include("lwipopts_extra.h") -#include "lwipopts_extra.h" -#endif -#include "lwipopts_default.h" + #if __has_include("lwipopts_extra.h") + #include "lwipopts_extra.h" + #endif + #include "lwipopts_default.h" #endif #endif /* _ARDUINO_LWIPOPTS_H */ diff --git a/src/lwipopts_default.h b/src/lwipopts_default.h index f13b274..d7fae2d 100644 --- a/src/lwipopts_default.h +++ b/src/lwipopts_default.h @@ -151,35 +151,35 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums #ifdef CHECKSUM_BY_HARDWARE -/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/ -#define CHECKSUM_GEN_IP 0 -/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/ -#define CHECKSUM_GEN_UDP 0 -/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/ -#define CHECKSUM_GEN_TCP 0 -/* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/ -#define CHECKSUM_CHECK_IP 0 -/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/ -#define CHECKSUM_CHECK_UDP 0 -/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/ -#define CHECKSUM_CHECK_TCP 0 -/* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/ -#define CHECKSUM_GEN_ICMP 0 + /* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/ + #define CHECKSUM_GEN_IP 0 + /* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/ + #define CHECKSUM_GEN_UDP 0 + /* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/ + #define CHECKSUM_GEN_TCP 0 + /* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/ + #define CHECKSUM_CHECK_IP 0 + /* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/ + #define CHECKSUM_CHECK_UDP 0 + /* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/ + #define CHECKSUM_CHECK_TCP 0 + /* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/ + #define CHECKSUM_GEN_ICMP 0 #else -/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/ -#define CHECKSUM_GEN_IP 1 -/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/ -#define CHECKSUM_GEN_UDP 1 -/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/ -#define CHECKSUM_GEN_TCP 1 -/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/ -#define CHECKSUM_CHECK_IP 1 -/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/ -#define CHECKSUM_CHECK_UDP 1 -/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/ -#define CHECKSUM_CHECK_TCP 1 -/* CHECKSUM_CHECK_ICMP==1: Check checksums by hardware for incoming ICMP packets.*/ -#define CHECKSUM_GEN_ICMP 1 + /* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/ + #define CHECKSUM_GEN_IP 1 + /* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/ + #define CHECKSUM_GEN_UDP 1 + /* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/ + #define CHECKSUM_GEN_TCP 1 + /* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/ + #define CHECKSUM_CHECK_IP 1 + /* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/ + #define CHECKSUM_CHECK_UDP 1 + /* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/ + #define CHECKSUM_CHECK_TCP 1 + /* CHECKSUM_CHECK_ICMP==1: Check checksums by hardware for incoming ICMP packets.*/ + #define CHECKSUM_GEN_ICMP 1 #endif diff --git a/src/utility/ethernetif.cpp b/src/utility/ethernetif.cpp index 31aa806..d254ece 100644 --- a/src/utility/ethernetif.cpp +++ b/src/utility/ethernetif.cpp @@ -54,7 +54,7 @@ #include "lwip/igmp.h" #include "stm32_eth.h" #if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01050000) -#include "variant.h" + #include "variant.h" #endif #ifdef __cplusplus diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index 22b3fa7..1148ab0 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -63,8 +63,8 @@ * They could be used for this library when available */ #ifndef DEFAULT_ETHERNET_TIMER -#define DEFAULT_ETHERNET_TIMER TIM14 -#warning "Default timer used to call ethernet scheduler at regular interval: TIM14" + #define DEFAULT_ETHERNET_TIMER TIM14 + #warning "Default timer used to call ethernet scheduler at regular interval: TIM14" #endif /* Ethernet configuration: user parameters */ @@ -93,8 +93,8 @@ static uint8_t DHCP_Started_by_user = 0; static uint32_t gEhtLinkTickStart = 0; #if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100) -/* Handler for stimer */ -static stimer_t TimHandle; + /* Handler for stimer */ + static stimer_t TimHandle; #endif /*************************** Function prototype *******************************/ @@ -137,11 +137,11 @@ static void Netif_Config(void) * @retval None */ #if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100) -static void scheduler_callback(stimer_t *htim) + static void scheduler_callback(stimer_t *htim) #elif (STM32_CORE_VERSION <= 0x01080000) -static void scheduler_callback(HardwareTimer *htim) + static void scheduler_callback(HardwareTimer *htim) #else -static void scheduler_callback(void) + static void scheduler_callback(void) #endif { #if (STM32_CORE_VERSION <= 0x01080000) diff --git a/src/utility/stm32_eth.h b/src/utility/stm32_eth.h index 4866be6..d4c3ff2 100644 --- a/src/utility/stm32_eth.h +++ b/src/utility/stm32_eth.h @@ -112,7 +112,7 @@ struct tcp_struct { #define MAX_CLIENT 32 #ifdef ETH_INPUT_USE_IT -extern struct netif gnetif; + extern struct netif gnetif; #endif @@ -125,22 +125,22 @@ void stm32_eth_scheduler(void); void User_notification(struct netif *netif); #if LWIP_DHCP -void stm32_DHCP_Process(struct netif *netif); -void stm32_DHCP_Periodic_Handle(struct netif *netif); -void stm32_DHCP_manual_config(void); -uint8_t stm32_get_DHCP_lease_state(void); -void stm32_set_DHCP_state(uint8_t state); -uint8_t stm32_get_DHCP_state(void); -uint8_t stm32_dhcp_started(void); + void stm32_DHCP_Process(struct netif *netif); + void stm32_DHCP_Periodic_Handle(struct netif *netif); + void stm32_DHCP_manual_config(void); + uint8_t stm32_get_DHCP_lease_state(void); + void stm32_set_DHCP_state(uint8_t state); + uint8_t stm32_get_DHCP_state(void); + uint8_t stm32_dhcp_started(void); #else -#error "LWIP_DHCP must be enabled in lwipopts.h" + #error "LWIP_DHCP must be enabled in lwipopts.h" #endif #if LWIP_DNS -void stm32_dns_init(const uint8_t *dnsaddr); -int8_t stm32_dns_gethostbyname(const char *hostname, uint32_t *ipaddr); + void stm32_dns_init(const uint8_t *dnsaddr); + int8_t stm32_dns_gethostbyname(const char *hostname, uint32_t *ipaddr); #else -#error "LWIP_DNS must be enabled in lwipopts.h" + #error "LWIP_DNS must be enabled in lwipopts.h" #endif #if LWIP_UDP @@ -164,11 +164,11 @@ ip_addr_t *u8_to_ip_addr(uint8_t *ipu8, ip_addr_t *ipaddr); uint32_t ip_addr_to_u32(ip_addr_t *ipaddr); #if LWIP_TCP -err_t tcp_connected_callback(void *arg, struct tcp_pcb *tpcb, err_t err); -err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err); -void tcp_connection_close(struct tcp_pcb *tpcb, struct tcp_struct *tcp); + err_t tcp_connected_callback(void *arg, struct tcp_pcb *tpcb, err_t err); + err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err); + void tcp_connection_close(struct tcp_pcb *tpcb, struct tcp_struct *tcp); #else -#error "LWIP_TCP must be enabled in lwipopts.h" + #error "LWIP_TCP must be enabled in lwipopts.h" #endif #endif /* __STM32_ETH_H__ */ From a1f708d4a6937abd05f13084620dbcc07948986f Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 5 Oct 2021 18:37:56 +0200 Subject: [PATCH 31/58] ci: change to main branch Signed-off-by: Frederic Pillon --- .github/workflows/Continuous-Integration.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/Continuous-Integration.yml b/.github/workflows/Continuous-Integration.yml index 982a286..0547884 100644 --- a/.github/workflows/Continuous-Integration.yml +++ b/.github/workflows/Continuous-Integration.yml @@ -2,7 +2,7 @@ name: STM32Ethernet Continuous Integration on: push: branches: - - master + - main paths-ignore: - '*' - '**.md' @@ -19,11 +19,11 @@ jobs: steps: # First of all, clone the repo using the checkout action. - name: Checkout - uses: actions/checkout@master + uses: actions/checkout@main - name: Astyle check id: Astyle - uses: stm32duino/actions/astyle-check@master + uses: stm32duino/actions/astyle-check@main # Use the output from the `Astyle` step - name: Astyle Errors @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest name: Spell check steps: - - uses: actions/checkout@master + - uses: actions/checkout@main - uses: arduino/actions/libraries/spell-check@master # with: # ignore-words-list: "./extras/codespell-ignore-words-list.txt" @@ -45,11 +45,11 @@ jobs: steps: # First of all, clone the repo using the checkout action. - name: Checkout - uses: actions/checkout@master + uses: actions/checkout@main - name: Compilation id: Compile - uses: stm32duino/actions/compile-examples@master + uses: stm32duino/actions/compile-examples@main with: board-pattern: "DISCO_F746NG|NUCLEO_F429ZI|NUCLEO_F767ZI" libraries: "STM32duino LwIP" From abcf362a8438d4f79ec705babe71c162b232940f Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Mon, 28 Feb 2022 16:33:04 +0100 Subject: [PATCH 32/58] ci: add library STM32duino FreeRTOS --- .github/workflows/Continuous-Integration.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Continuous-Integration.yml b/.github/workflows/Continuous-Integration.yml index 0547884..b324ceb 100644 --- a/.github/workflows/Continuous-Integration.yml +++ b/.github/workflows/Continuous-Integration.yml @@ -52,11 +52,11 @@ jobs: uses: stm32duino/actions/compile-examples@main with: board-pattern: "DISCO_F746NG|NUCLEO_F429ZI|NUCLEO_F767ZI" - libraries: "STM32duino LwIP" + libraries: "STM32duino LwIP, STM32duino FreeRTOS" # Use the output from the `Compile` step - name: Compilation Errors if: failure() run: | cat ${{ steps.Compile.outputs.compile-result }} - exit 1 \ No newline at end of file + exit 1 From 7669880d8f1347b45f4bc2749ce9ef3eaf2b40ba Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Fri, 25 Feb 2022 18:19:01 +0100 Subject: [PATCH 33/58] feat: Add examples to demonstrate how to use FreeRTOS with Ethernet Both WebClientFreeRTOS and WebServerFreeRTOS are available. Warning: FreeRTOS may disable interrupts between xTaskCreate() and vTaskStartScheduler(). Thus Ethernet, which is using Interrupts, should be initialized after scheduling start. thus it is done within a task. Fixes #36 Signed-off-by: Alexandre Bourdiol --- .../WebClientFreeRTOS/WebClientFreeRTOS.ino | 104 +++++++++++++ .../WebServerFreeRTOS/WebServerFreeRTOS.ino | 139 ++++++++++++++++++ 2 files changed, 243 insertions(+) create mode 100644 examples/WebClientFreeRTOS/WebClientFreeRTOS.ino create mode 100644 examples/WebServerFreeRTOS/WebServerFreeRTOS.ino diff --git a/examples/WebClientFreeRTOS/WebClientFreeRTOS.ino b/examples/WebClientFreeRTOS/WebClientFreeRTOS.ino new file mode 100644 index 0000000..842f244 --- /dev/null +++ b/examples/WebClientFreeRTOS/WebClientFreeRTOS.ino @@ -0,0 +1,104 @@ +/* + Port of WebClient on FreeRTOS + + This sketch connects to a website (http://www.google.com) + + Circuit: + * STM32 board with Ethernet support + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe, based on work by Adrian McEwen + modified 23 Jun 2017 + by Wi6Labs + modified 1 Jun 2018 + by sstaub + */ + +#include +#include +#include + +// if you don't want to use DNS (and reduce your sketch size) +// use the numeric IP instead of the name for the server: +//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS) +char server[] = "www.google.com"; // name address for Google (using DNS) + +// Set the static IP address to use if the DHCP fails to assign +IPAddress ip(192, 168, 0, 177); + +// Initialize the Ethernet client library +// with the IP address and port of the server +// that you want to connect to (port 80 is default for HTTP): +EthernetClient client; + + +// task code +void taskETH(void* arg) { + UNUSED(arg); + // start the Ethernet connection: + if (Ethernet.begin() == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // try to configure using IP address instead of DHCP: + Ethernet.begin(ip); + } + // give the Ethernet shield a second to initialize: + delay(1000); + Serial.println("connecting..."); + + // if you get a connection, report back via serial: + if (client.connect(server, 80)) { + Serial.println("connected"); + // Make a HTTP request: + client.println("GET /search?q=arduino HTTP/1.1"); + client.println("Host: www.google.com"); + client.println("Connection: close"); + client.println(); + } else { + // if you didn't get a connection to the server: + Serial.println("connection failed"); + } + + while(1){ + // if there are incoming bytes available + // from the server, read them and print them: + if (client.available()) { + char c = client.read(); + Serial.print(c); + } + + // if the server's disconnected, stop the client: + if (!client.connected()) { + Serial.println(); + Serial.println("disconnecting."); + client.stop(); + + // do nothing forevermore: + while (true); + } + } +} + + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + portBASE_TYPE s = xTaskCreate(taskETH, NULL, 200, NULL, 1, NULL); + if (s != pdPASS) { + printf("Ethernet task creation failed\n"); + while (1); + } + + vTaskStartScheduler(); + Serial.println("Scheduler failed"); + while (1); +} + +void loop() { + // Not used. +} diff --git a/examples/WebServerFreeRTOS/WebServerFreeRTOS.ino b/examples/WebServerFreeRTOS/WebServerFreeRTOS.ino new file mode 100644 index 0000000..f69b68b --- /dev/null +++ b/examples/WebServerFreeRTOS/WebServerFreeRTOS.ino @@ -0,0 +1,139 @@ +/* + Port of WebServer on FreeRTOS + + A simple web server that shows the value of the analog input pins. + 2 task are created: + Ethernet: to manage the server + Analog to read input values + + Circuit: + STM32 board with Ethernet support + Analog inputs attached to pins A0 through A5 (optional) + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe + modified 02 Sept 2015 + by Arturo Guadalupi + modified 23 Jun 2017 + by Wi6Labs + modified 1 Jun 2018 + by sstaub +*/ + +#include +#include +#include + +// Enter an IP address for your controller below. +// The IP address will be dependent on your local network: +IPAddress ip(192, 168, 0, 177); + +// Initialize the Ethernet server library +// with the IP address and port you want to use +// (port 80 is default for HTTP): +EthernetServer server(80); + +#define ANALOG_CHANEL_NUMBER 6 +int sensorReading[ANALOG_CHANEL_NUMBER]; + +void taskAnalog(void* arg) { + UNUSED(arg); + while (1) { + for (int analogChannel = 0; analogChannel < ANALOG_CHANEL_NUMBER; analogChannel++) { + sensorReading[analogChannel] = analogRead(analogChannel); + } + vTaskDelay(1000); // read Analog every seconds + } +} + +// task code +void taskETH(void* arg) { + UNUSED(arg); + // start the Ethernet connection and the server: + Ethernet.begin(ip); + server.begin(); + Serial.print("server is at "); + Serial.println(Ethernet.localIP()); + + while (1) { + // listen for incoming clients + EthernetClient client = server.available(); + if (client) { + Serial.println("new client"); + // an http request ends with a blank line + bool currentLineIsBlank = true; + while (client.connected()) { + if (client.available()) { + char c = client.read(); + Serial.write(c); + // if you've gotten to the end of the line (received a newline + // character) and the line is blank, the http request has ended, + // so you can send a reply + if (c == '\n' && currentLineIsBlank) { + // send a standard http response header + client.println("HTTP/1.1 200 OK"); + client.println("Content-Type: text/html"); + client.println("Connection: close"); // the connection will be closed after completion of the response + client.println("Refresh: 5"); // refresh the page automatically every 5 sec + client.println(); + client.println(""); + client.println(""); + // output the value of each analog input pin + for (int analogChannel = 0; analogChannel < ANALOG_CHANEL_NUMBER; analogChannel++) { + client.print("analog input "); + client.print(analogChannel); + client.print(" is "); + client.print(sensorReading[analogChannel]); + client.println("
"); + } + client.println(""); + break; + } + if (c == '\n') { + // you're starting a new line + currentLineIsBlank = true; + } else if (c != '\r') { + // you've gotten a character on the current line + currentLineIsBlank = false; + } + } + } + // give the web browser time to receive the data + delay(1); + // close the connection: + client.stop(); + Serial.println("client disconnected"); + } + } +} + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + portBASE_TYPE s = xTaskCreate(taskETH, NULL, 200, NULL, 1, NULL); + if (s != pdPASS) { + printf("Ethernet task creation failed\n"); + while (1); + } + + s = xTaskCreate(taskAnalog, NULL, 200, NULL, 2, NULL); + if (s != pdPASS) { + printf("Analog task creation failed\n"); + while (1); + } + + vTaskStartScheduler(); + Serial.println("Scheduler failed"); + while (1); +} + + +void loop() { + // Not used. +} \ No newline at end of file From c191eade02474154318584b9d0726d8a818e3a2a Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Tue, 1 Mar 2022 16:49:23 +0100 Subject: [PATCH 34/58] fix: Assume DNS is the same IP than gateway When DNS is not provided, it is more likely to be the same than gateway (more likely than xx.xx.xx.1) Signed-off-by: Alexandre Bourdiol --- src/STM32Ethernet.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/STM32Ethernet.cpp b/src/STM32Ethernet.cpp index 77313a6..a0753de 100644 --- a/src/STM32Ethernet.cpp +++ b/src/STM32Ethernet.cpp @@ -33,11 +33,8 @@ void EthernetClass::begin(IPAddress local_ip, IPAddress subnet) void EthernetClass::begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway) { - // Assume the DNS server will be the machine on the same network as the local IP - // but with last octet being '1' - IPAddress dns_server = local_ip; - dns_server[3] = 1; - begin(local_ip, subnet, gateway, dns_server); + // Assume the DNS server will be the same machine than gateway + begin(local_ip, subnet, gateway, gateway); } void EthernetClass::begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server) From d5993db2dc7c13d682418d409c03cb7f91fb64e5 Mon Sep 17 00:00:00 2001 From: Solariseir Date: Fri, 11 Mar 2022 11:29:01 +0100 Subject: [PATCH 35/58] fix: if DHCP fails the static IP can be applied without problem (#50) and adding timeout to client connection Co-authored-by: Alexandre Bourdiol <50730894+ABOSTM@users.noreply.github.com> Co-authored-by: Frederic Pillon --- src/EthernetClient.cpp | 5 ++-- src/EthernetClient.h | 5 ++++ src/utility/stm32_eth.cpp | 51 +++++++++++++++++++++------------------ 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/EthernetClient.cpp b/src/EthernetClient.cpp index 5db2e47..4fd0a7f 100644 --- a/src/EthernetClient.cpp +++ b/src/EthernetClient.cpp @@ -65,6 +65,7 @@ int EthernetClient::connect(IPAddress ip, uint16_t port) _tcp_client->data.available = 0; _tcp_client->state = TCP_NONE; + uint32_t startTime = millis(); ip_addr_t ipaddr; tcp_arg(_tcp_client->pcb, _tcp_client); if (ERR_OK != tcp_connect(_tcp_client->pcb, u8_to_ip_addr(rawIPAddress(ip), &ipaddr), port, &tcp_connected_callback)) { @@ -72,10 +73,10 @@ int EthernetClient::connect(IPAddress ip, uint16_t port) return 0; } - uint32_t startTime = millis(); + startTime = millis(); while (_tcp_client->state == TCP_NONE) { stm32_eth_scheduler(); - if ((_tcp_client->state == TCP_CLOSING) || ((millis() - startTime) >= 10000)) { + if ((_tcp_client->state == TCP_CLOSING) || ((millis() - startTime) >= _timeout)) { stop(); return 0; } diff --git a/src/EthernetClient.h b/src/EthernetClient.h index 251b580..c937a05 100644 --- a/src/EthernetClient.h +++ b/src/EthernetClient.h @@ -52,6 +52,10 @@ class EthernetClient : public Client { { return (_tcp_client->pcb->remote_port); }; + void setTimeout(uint16_t timeout) + { + _timeout = timeout; + } friend class EthernetServer; @@ -59,6 +63,7 @@ class EthernetClient : public Client { private: struct tcp_struct *_tcp_client; + uint16_t _timeout = 10000; }; #endif diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index 1148ab0..73c49a0 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -111,6 +111,7 @@ static void TIM_scheduler_Config(void); */ static void Netif_Config(void) { + netif_remove(&gnetif); /* Add the network interface */ netif_add(&gnetif, &(gconfig.ipaddr), &(gconfig.netmask), &(gconfig.gw), NULL, ðernetif_init, ðernet_input); @@ -176,6 +177,7 @@ static void TIM_scheduler_Config(void) { /* Configure HardwareTimer */ HardwareTimer *EthTim = new HardwareTimer(DEFAULT_ETHERNET_TIMER); + EthTim->setMode(1, TIMER_OUTPUT_COMPARE); /* Timer set to 1ms */ EthTim->setOverflow(1000, MICROSEC_FORMAT); @@ -191,47 +193,48 @@ void stm32_eth_init(const uint8_t *mac, const uint8_t *ip, const uint8_t *gw, co if (!initDone) { /* Initialize the LwIP stack */ lwip_init(); + } - if (mac != NULL) { - ethernetif_set_mac_addr(mac); - } // else default value is used: MAC_ADDR0 ... MAC_ADDR5 + if (mac != NULL) { + ethernetif_set_mac_addr(mac); + } // else default value is used: MAC_ADDR0 ... MAC_ADDR5 - if (ip != NULL) { - IP_ADDR4(&(gconfig.ipaddr), ip[0], ip[1], ip[2], ip[3]); - } else { + if (ip != NULL) { + IP_ADDR4(&(gconfig.ipaddr), ip[0], ip[1], ip[2], ip[3]); + } else { #if LWIP_DHCP - ip_addr_set_zero_ip4(&(gconfig.ipaddr)); + ip_addr_set_zero_ip4(&(gconfig.ipaddr)); #else - IP_ADDR4(&(gconfig.ipaddr), IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); + IP_ADDR4(&(gconfig.ipaddr), IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); #endif /* LWIP_DHCP */ - } + } - if (gw != NULL) { - IP_ADDR4(&(gconfig.gw), gw[0], gw[1], gw[2], gw[3]); - } else { + if (gw != NULL) { + IP_ADDR4(&(gconfig.gw), gw[0], gw[1], gw[2], gw[3]); + } else { #if LWIP_DHCP - ip_addr_set_zero_ip4(&(gconfig.gw)); + ip_addr_set_zero_ip4(&(gconfig.gw)); #else - IP_ADDR4(&(gconfig.gw), GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + IP_ADDR4(&(gconfig.gw), GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); #endif /* LWIP_DHCP */ - } + } - if (netmask != NULL) { - IP_ADDR4(&(gconfig.netmask), netmask[0], netmask[1], netmask[2], netmask[3]); - } else { + if (netmask != NULL) { + IP_ADDR4(&(gconfig.netmask), netmask[0], netmask[1], netmask[2], netmask[3]); + } else { #if LWIP_DHCP - ip_addr_set_zero_ip4(&(gconfig.netmask)); + ip_addr_set_zero_ip4(&(gconfig.netmask)); #else - IP_ADDR4(&(gconfig.netmask), NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); + IP_ADDR4(&(gconfig.netmask), NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); #endif /* LWIP_DHCP */ - } + } - /* Configure the Network interface */ - Netif_Config(); + /* Configure the Network interface */ + Netif_Config(); + if (!initDone) { // stm32_eth_scheduler() will be called every 1ms. TIM_scheduler_Config(); - initDone = 1; } From e2e0a42d6ecd958baa49600ede67b8d4f837c73e Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Mon, 14 Mar 2022 15:07:50 +0100 Subject: [PATCH 36/58] fix: call effective ETH scheduler only from Timer callback Restrict effective ETH scheduler to Timer callback only. This is to avoid any race condition on ETH scheduler, which could previously be called from timer ISR, as well as DHCP or UDP driver parts. Any direct request for ETH scheduler (direct call to stm32_eth_scheduler()) will generate a Timer Update Event to force a call to timer callback Fixes #45 Signed-off-by: Alexandre Bourdiol --- src/utility/stm32_eth.cpp | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index 73c49a0..937a297 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -95,6 +95,8 @@ static uint32_t gEhtLinkTickStart = 0; #if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100) /* Handler for stimer */ static stimer_t TimHandle; +#else + HardwareTimer *EthTim = NULL; #endif /*************************** Function prototype *******************************/ @@ -103,6 +105,9 @@ static err_t tcp_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, static err_t tcp_sent_callback(void *arg, struct tcp_pcb *tpcb, u16_t len); static void tcp_err_callback(void *arg, err_t err); static void TIM_scheduler_Config(void); +#if defined(STM32_CORE_VERSION) && (STM32_CORE_VERSION > 0x01060100) + void _stm32_eth_scheduler(void); +#endif /** * @brief Configurates the network interface @@ -148,7 +153,7 @@ static void Netif_Config(void) #if (STM32_CORE_VERSION <= 0x01080000) UNUSED(htim); #endif - stm32_eth_scheduler(); + _stm32_eth_scheduler(); } #if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100) @@ -176,7 +181,7 @@ static void TIM_scheduler_Config(void) static void TIM_scheduler_Config(void) { /* Configure HardwareTimer */ - HardwareTimer *EthTim = new HardwareTimer(DEFAULT_ETHERNET_TIMER); + EthTim = new HardwareTimer(DEFAULT_ETHERNET_TIMER); EthTim->setMode(1, TIMER_OUTPUT_COMPARE); /* Timer set to 1ms */ @@ -265,12 +270,33 @@ uint8_t stm32_eth_link_up(void) return netif_is_link_up(&gnetif); } +#if defined(STM32_CORE_VERSION) && (STM32_CORE_VERSION > 0x01060100) +/** + * @brief This function generates Timer Update event to force call to _stm32_eth_scheduler(). + * @param None + * @retval None + */ +void stm32_eth_scheduler(void) +{ + if (EthTim != NULL) { + EthTim->refresh(); + } +} + /** - * @brief This function must be called in main loop in standalone mode. + * @brief This function is called solely by Timer callback to avoid race condition. + * @param None + * @retval None + */ +void _stm32_eth_scheduler(void) +#else +/** + * @brief This function is called solely by Timer callback to avoid race condition. * @param None * @retval None */ void stm32_eth_scheduler(void) +#endif { /* Read a received packet from the Ethernet buffers and send it to the lwIP for handling */ From fb56c5415898bfa7d1cbcaee3670b7a048309c3c Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Wed, 13 Apr 2022 10:20:40 +0200 Subject: [PATCH 37/58] Fix : Wrong _tcp_client[] array initialization Former "_tcp_client[MAX_CLIENT] = {};" tries to initialize the array element with index MAX_CLIENT, which is out of array range [0 .. (MAX_CLIENT-1)] Fixes warning: warning: array subscript 32 is above array bounds of 'tcp_struct* [32]' [-Warray-bounds] Instead initialize each element of the array one by one. Signed-off-by: Alexandre Bourdiol --- src/EthernetServer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/EthernetServer.cpp b/src/EthernetServer.cpp index e006b83..5f59785 100644 --- a/src/EthernetServer.cpp +++ b/src/EthernetServer.cpp @@ -9,7 +9,9 @@ extern "C" { EthernetServer::EthernetServer(uint16_t port) { _port = port; - _tcp_client[MAX_CLIENT] = {}; + for (int i = 0; i < MAX_CLIENT; i++) { + _tcp_client[i] = {}; + } _tcp_server = {}; } From 89e4523991ee8dd9235f9a370c702a0df45911df Mon Sep 17 00:00:00 2001 From: patricklaf Date: Mon, 25 Apr 2022 16:58:03 +0200 Subject: [PATCH 38/58] feat: Add function to define port of EthernetServer at runtime --- src/EthernetServer.cpp | 6 ++++++ src/EthernetServer.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/EthernetServer.cpp b/src/EthernetServer.cpp index 5f59785..386ae9d 100644 --- a/src/EthernetServer.cpp +++ b/src/EthernetServer.cpp @@ -40,6 +40,12 @@ void EthernetServer::begin() tcp_accept(_tcp_server.pcb, tcp_accept_callback); } +void EthernetServer::begin(uint16_t port) +{ + _port = port; + begin(); +} + void EthernetServer::accept() { /* Free client if disconnected */ diff --git a/src/EthernetServer.h b/src/EthernetServer.h index 60fac5b..3a218d4 100644 --- a/src/EthernetServer.h +++ b/src/EthernetServer.h @@ -17,6 +17,7 @@ class EthernetServer : EthernetServer(uint16_t port = 80); EthernetClient available(); virtual void begin(); + virtual void begin(uint16_t port); virtual size_t write(uint8_t); virtual size_t write(const uint8_t *buf, size_t size); using Print::write; From 3d930a62337a72fef44f5ecaa6feb79451d39b88 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 26 Apr 2022 10:15:47 +0200 Subject: [PATCH 39/58] chore: bump version --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index d6b7529..f4f202c 100755 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/stm32duino/STM32Ethernet" }, - "version": "1.2.0", + "version": "1.3.0", "frameworks": "arduino", "platforms": "ststm32", "build": { From cc1e72d64fe0aaa8b3b9a9e18c093b25af6daaae Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 26 Apr 2022 10:16:23 +0200 Subject: [PATCH 40/58] chore: bump version --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index da4cf0a..3a4aaee 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino STM32Ethernet -version=1.2.0 +version=1.3.0 author=Various maintainer=STMicroelectronics sentence=Enables network connection (local and Internet) using the STM32 Board. From a55d412ba90f78481cf3ff0e975024b3c9b4f028 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 13 Sep 2022 13:47:47 +0200 Subject: [PATCH 41/58] fix: typo raised by spellcheck --- src/lwipopts_default.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lwipopts_default.h b/src/lwipopts_default.h index d7fae2d..f605098 100644 --- a/src/lwipopts_default.h +++ b/src/lwipopts_default.h @@ -51,7 +51,7 @@ a lot of data that needs to be copied, this should be set high. */ /* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One per active UDP "connection". */ #define MEMP_NUM_UDP_PCB 6 -/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP +/* MEMP_NUM_TCP_PCB: the number of simultaneously active TCP connections. */ #define MEMP_NUM_TCP_PCB 10 /* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP @@ -60,7 +60,7 @@ a lot of data that needs to be copied, this should be set high. */ /* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. */ #define MEMP_NUM_TCP_SEG 8 -/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active +/* MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active timeouts. */ #define MEMP_NUM_SYS_TIMEOUT 10 From b9cd0a34f9b5d9a8bfae37b22e101c2c7eea2b7f Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Tue, 13 Sep 2022 09:19:33 +0200 Subject: [PATCH 42/58] fix: set Ethernet Timer priority to 15 Aim is to have Ethernet Timer priority lower (higher value) than Systick (including FreeRTOS usecase) Signed-off-by: Alexandre Bourdiol --- src/utility/stm32_eth.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index 937a297..7b06955 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -67,6 +67,13 @@ #warning "Default timer used to call ethernet scheduler at regular interval: TIM14" #endif +/* Interrupt priority */ +#ifndef ETH_TIM_IRQ_PRIO + #define ETH_TIM_IRQ_PRIO 15 // Warning: it should be lower prio (higher value) than Systick +#endif +#ifndef ETH_TIM_IRQ_SUBPRIO + #define ETH_TIM_IRQ_SUBPRIO 0 +#endif /* Ethernet configuration: user parameters */ struct stm32_eth_config { ip_addr_t ipaddr; @@ -182,6 +189,7 @@ static void TIM_scheduler_Config(void) { /* Configure HardwareTimer */ EthTim = new HardwareTimer(DEFAULT_ETHERNET_TIMER); + EthTim->setInterruptPriority(ETH_TIM_IRQ_PRIO, ETH_TIM_IRQ_SUBPRIO); EthTim->setMode(1, TIMER_OUTPUT_COMPARE); /* Timer set to 1ms */ From aa551125b9132619d3d28a9196b7f8a4e7d7ff69 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 24 Nov 2022 11:48:54 +0100 Subject: [PATCH 43/58] ci: replace deprecated spellcheck by codespell --- .github/workflows/Continuous-Integration.yml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/Continuous-Integration.yml b/.github/workflows/Continuous-Integration.yml index b324ceb..259d70f 100644 --- a/.github/workflows/Continuous-Integration.yml +++ b/.github/workflows/Continuous-Integration.yml @@ -31,14 +31,21 @@ jobs: run: | cat ${{ steps.Astyle.outputs.astyle-result }} exit 1 - spell-check: + codespell: + name: Check for spelling errors runs-on: ubuntu-latest - name: Spell check steps: - - uses: actions/checkout@main - - uses: arduino/actions/libraries/spell-check@master - # with: - # ignore-words-list: "./extras/codespell-ignore-words-list.txt" + - name: Checkout + uses: actions/checkout@main + + # See: https://github.com/codespell-project/actions-codespell/blob/master/README.md + - name: Spell check + uses: codespell-project/actions-codespell@master + with: + check_filenames: true + check_hidden: true + # In the event of a false positive, add the word in all lower case to this file: + # ignore_words_file: ./extras/codespell-ignore-words-list.txt lib_build: runs-on: ubuntu-latest name: Library compilation From 947471903b5099c6465ab2e474891decc0753059 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 28 Sep 2023 09:58:48 +0200 Subject: [PATCH 44/58] fix(client): setTimeout shadows Stream.setTimeout Rename it setConnectionTimeout to match Arduino Ethernet API. Fixes #72 Signed-off-by: Frederic Pillon --- keywords.txt | 1 + src/EthernetClient.cpp | 2 +- src/EthernetClient.h | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/keywords.txt b/keywords.txt index 367603a..e4af683 100644 --- a/keywords.txt +++ b/keywords.txt @@ -34,6 +34,7 @@ getSocketNumber KEYWORD2 localIP KEYWORD2 MACAddress KEYWORD2 maintain KEYWORD2 +setConnectionTimeout KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/src/EthernetClient.cpp b/src/EthernetClient.cpp index 4fd0a7f..b4ad99c 100644 --- a/src/EthernetClient.cpp +++ b/src/EthernetClient.cpp @@ -76,7 +76,7 @@ int EthernetClient::connect(IPAddress ip, uint16_t port) startTime = millis(); while (_tcp_client->state == TCP_NONE) { stm32_eth_scheduler(); - if ((_tcp_client->state == TCP_CLOSING) || ((millis() - startTime) >= _timeout)) { + if ((_tcp_client->state == TCP_CLOSING) || ((millis() - startTime) >= _connectionTimeout)) { stop(); return 0; } diff --git a/src/EthernetClient.h b/src/EthernetClient.h index c937a05..5afb160 100644 --- a/src/EthernetClient.h +++ b/src/EthernetClient.h @@ -52,9 +52,9 @@ class EthernetClient : public Client { { return (_tcp_client->pcb->remote_port); }; - void setTimeout(uint16_t timeout) + void setConnectionTimeout(uint16_t timeout) { - _timeout = timeout; + _connectionTimeout = timeout; } friend class EthernetServer; @@ -63,7 +63,7 @@ class EthernetClient : public Client { private: struct tcp_struct *_tcp_client; - uint16_t _timeout = 10000; + uint16_t _connectionTimeout = 10000; }; #endif From 6d46fb08c953119a9dd462fe790b0106bb54417e Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 28 Sep 2023 09:59:37 +0200 Subject: [PATCH 45/58] chore(keywords.txt): add missing keywords Signed-off-by: Frederic Pillon --- keywords.txt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/keywords.txt b/keywords.txt index e4af683..09e494c 100644 --- a/keywords.txt +++ b/keywords.txt @@ -24,7 +24,9 @@ peek KEYWORD2 flush KEYWORD2 stop KEYWORD2 connected KEYWORD2 +accept KEYWORD2 begin KEYWORD2 +beginMulticast KEYWORD2 beginPacket KEYWORD2 endPacket KEYWORD2 parsePacket KEYWORD2 @@ -32,11 +34,17 @@ remoteIP KEYWORD2 remotePort KEYWORD2 getSocketNumber KEYWORD2 localIP KEYWORD2 -MACAddress KEYWORD2 +localPort KEYWORD2 maintain KEYWORD2 +linkStatus KEYWORD2 +MACAddress KEYWORD2 +subnetMask KEYWORD2 +gatewayIP KEYWORD2 +dnsServerIP KEYWORD2 setConnectionTimeout KEYWORD2 ####################################### # Constants (LITERAL1) ####################################### - +LinkON LITERAL1 +LinkOFF LITERAL1 From df784287cd0e7468e88596c9517e0347609bc448 Mon Sep 17 00:00:00 2001 From: jeremyB01 <149951864+jeremyB01@users.noreply.github.com> Date: Mon, 6 Nov 2023 20:16:11 +0100 Subject: [PATCH 46/58] Fixing bug that caused large memory consumption Signed-off-by: jeremyB01 <149951864+jeremyB01@users.noreply.github.com> --- src/EthernetClient.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/EthernetClient.cpp b/src/EthernetClient.cpp index b4ad99c..aa2606b 100644 --- a/src/EthernetClient.cpp +++ b/src/EthernetClient.cpp @@ -194,6 +194,7 @@ void EthernetClient::stop() if (status() != TCP_CLOSING) { tcp_connection_close(_tcp_client->pcb, _tcp_client); } + mem_free(_tcp_client); } uint8_t EthernetClient::connected() From c4b0663f8b88d0cb05fe5f2ea56fbdf755434151 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 7 Nov 2023 15:48:49 +0100 Subject: [PATCH 47/58] fix(doc): wiki link Signed-off-by: Frederic Pillon --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6e2262d..b87f2b2 100644 --- a/README.md +++ b/README.md @@ -66,4 +66,4 @@ Call `Ethernet::schedule()` performs an update of the LwIP stack.
## Wiki -You can find information at https://github.com/stm32duino/wiki/wiki/STM32Ethernet +You can find information at https://github.com/stm32duino/Arduino_Core_STM32/wiki/STM32Ethernet From 566dc84252edf2ee76d13fdd6114302287c3fcdc Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 7 Nov 2023 11:19:53 +0100 Subject: [PATCH 48/58] fix(server): do not use same variable name Signed-off-by: Frederic Pillon --- src/EthernetServer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/EthernetServer.cpp b/src/EthernetServer.cpp index 386ae9d..1355b88 100644 --- a/src/EthernetServer.cpp +++ b/src/EthernetServer.cpp @@ -93,10 +93,10 @@ size_t EthernetServer::write(const uint8_t *buffer, size_t size) accept(); - for (int n = 0; n < MAX_CLIENT; n++) { - if (_tcp_client[n] != NULL) { - if (_tcp_client[n]->pcb != NULL) { - EthernetClient client(_tcp_client[n]); + for (int i = 0; i < MAX_CLIENT; i++) { + if (_tcp_client[i] != NULL) { + if (_tcp_client[i]->pcb != NULL) { + EthernetClient client(_tcp_client[i]); uint8_t s = client.status(); if (s == TCP_ACCEPTED) { n += client.write(buffer, size); From 6b9664bac0db7f85563176135edd39f07e32a6b3 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 7 Nov 2023 11:21:06 +0100 Subject: [PATCH 49/58] feat(server): add bool operator Fixes #73. Signed-off-by: Frederic Pillon --- src/EthernetServer.cpp | 6 ++++++ src/EthernetServer.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/EthernetServer.cpp b/src/EthernetServer.cpp index 1355b88..81827d5 100644 --- a/src/EthernetServer.cpp +++ b/src/EthernetServer.cpp @@ -107,3 +107,9 @@ size_t EthernetServer::write(const uint8_t *buffer, size_t size) return n; } + +EthernetServer::operator bool() +{ + // server is listening for incoming clients + return ((_tcp_server.pcb != NULL) && (_tcp_server.pcb->state == LISTEN)); +} diff --git a/src/EthernetServer.h b/src/EthernetServer.h index 3a218d4..3205f6d 100644 --- a/src/EthernetServer.h +++ b/src/EthernetServer.h @@ -20,6 +20,7 @@ class EthernetServer : virtual void begin(uint16_t port); virtual size_t write(uint8_t); virtual size_t write(const uint8_t *buf, size_t size); + virtual operator bool(); using Print::write; }; From 88030146817040384e61df9e89651ac7ca13c23f Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Wed, 8 Nov 2023 14:42:28 +0100 Subject: [PATCH 50/58] feat(server): add end() Fixes #73. Signed-off-by: Frederic Pillon --- src/EthernetServer.cpp | 16 ++++++++++++++++ src/EthernetServer.h | 1 + 2 files changed, 17 insertions(+) diff --git a/src/EthernetServer.cpp b/src/EthernetServer.cpp index 81827d5..2082498 100644 --- a/src/EthernetServer.cpp +++ b/src/EthernetServer.cpp @@ -46,6 +46,22 @@ void EthernetServer::begin(uint16_t port) begin(); } +void EthernetServer::end(void) +{ + /* Free client */ + for (int n = 0; n < MAX_CLIENT; n++) { + if (_tcp_client[n] != NULL) { + EthernetClient client(_tcp_client[n]); + client.stop(); + _tcp_client[n] = NULL; + } + } + if (_tcp_server.pcb != NULL) { + tcp_close(_tcp_server.pcb); + _tcp_server.pcb = NULL; + } +} + void EthernetServer::accept() { /* Free client if disconnected */ diff --git a/src/EthernetServer.h b/src/EthernetServer.h index 3205f6d..10c306c 100644 --- a/src/EthernetServer.h +++ b/src/EthernetServer.h @@ -18,6 +18,7 @@ class EthernetServer : EthernetClient available(); virtual void begin(); virtual void begin(uint16_t port); + void end(void); virtual size_t write(uint8_t); virtual size_t write(const uint8_t *buf, size_t size); virtual operator bool(); From cd50f45d53fefd1b947b2a2552f672f328321a3f Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 9 Nov 2023 16:51:29 +0100 Subject: [PATCH 51/58] chore: bump library version Signed-off-by: Frederic Pillon --- library.json | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.json b/library.json index f4f202c..f8fe867 100755 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/stm32duino/STM32Ethernet" }, - "version": "1.3.0", + "version": "1.4.0", "frameworks": "arduino", "platforms": "ststm32", "build": { diff --git a/library.properties b/library.properties index 3a4aaee..a7e954a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino STM32Ethernet -version=1.3.0 +version=1.4.0 author=Various maintainer=STMicroelectronics sentence=Enables network connection (local and Internet) using the STM32 Board. From 7245be64d037f7dfe6595f1e479f86085315d385 Mon Sep 17 00:00:00 2001 From: Juraj Andrassy Date: Thu, 21 Dec 2023 19:21:37 +0100 Subject: [PATCH 52/58] EthernetClass - add setDnsServerIP as in Arduino Ethernet library --- src/STM32Ethernet.cpp | 5 +++++ src/STM32Ethernet.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/STM32Ethernet.cpp b/src/STM32Ethernet.cpp index a0753de..3925d0a 100644 --- a/src/STM32Ethernet.cpp +++ b/src/STM32Ethernet.cpp @@ -182,4 +182,9 @@ IPAddress EthernetClass::dnsServerIP() return _dnsServerAddress; } +void EthernetClass::setDnsServerIP(const IPAddress dns_server) +{ + _dnsServerAddress = dns_server; +} + EthernetClass Ethernet; diff --git a/src/STM32Ethernet.h b/src/STM32Ethernet.h index 502e256..c567ff6 100644 --- a/src/STM32Ethernet.h +++ b/src/STM32Ethernet.h @@ -50,6 +50,8 @@ class EthernetClass { IPAddress gatewayIP(); IPAddress dnsServerIP(); + void setDnsServerIP(const IPAddress dns_server); + friend class EthernetClient; friend class EthernetServer; }; From 52aba529c005e6e670a8483b090e78ab96a2ee17 Mon Sep 17 00:00:00 2001 From: Juraj Andrassy Date: Wed, 27 Dec 2023 20:04:02 +0100 Subject: [PATCH 53/58] EthernetClient.connect - return only 1 or 0 --- src/EthernetClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EthernetClient.cpp b/src/EthernetClient.cpp index aa2606b..9c71624 100644 --- a/src/EthernetClient.cpp +++ b/src/EthernetClient.cpp @@ -39,7 +39,7 @@ int EthernetClient::connect(const char *host, uint16_t port) if (ret == 1) { return connect(remote_addr, port); } else { - return ret; + return 0; } } From cc099cf6dbcc85171209e5f91c95db5a56238c05 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 10 Sep 2024 14:31:49 +0200 Subject: [PATCH 54/58] fix: typo raised by codespell Signed-off-by: Frederic Pillon --- src/utility/stm32_eth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index 7b06955..e1c9669 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -117,7 +117,7 @@ static void TIM_scheduler_Config(void); #endif /** -* @brief Configurates the network interface +* @brief Configure the network interface * @param None * @retval None */ From 293b2d9ee3813cde905081f4cb8e08074b792480 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 10 Sep 2024 11:09:07 +0200 Subject: [PATCH 55/58] fix: use default MAC address only if no MAC_ADDRx defined Anyway the MAC address get by the application is always 0 while the real address is correct. Will be fixed by latter commit. Signed-off-by: Frederic Pillon --- src/STM32Ethernet.cpp | 18 ++---------------- src/STM32Ethernet.h | 1 - src/utility/ethernetif.cpp | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/STM32Ethernet.cpp b/src/STM32Ethernet.cpp index 3925d0a..2a9aa3d 100644 --- a/src/STM32Ethernet.cpp +++ b/src/STM32Ethernet.cpp @@ -5,7 +5,7 @@ int EthernetClass::begin(unsigned long timeout, unsigned long responseTimeout) { static DhcpClass s_dhcp; _dhcp = &s_dhcp; - stm32_eth_init(MACAddressDefault(), NULL, NULL, NULL); + stm32_eth_init(NULL, NULL, NULL, NULL); // Now try to get our config info from a DHCP server int ret = _dhcp->beginWithDHCP(mac_address, timeout, responseTimeout); @@ -39,7 +39,7 @@ void EthernetClass::begin(IPAddress local_ip, IPAddress subnet, IPAddress gatewa void EthernetClass::begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server) { - stm32_eth_init(MACAddressDefault(), local_ip.raw_address(), gateway.raw_address(), subnet.raw_address()); + stm32_eth_init(NULL, local_ip.raw_address(), gateway.raw_address(), subnet.raw_address()); /* If there is a local DHCP informs it of our manual IP configuration to prevent IP conflict */ stm32_DHCP_manual_config(); @@ -133,20 +133,6 @@ void EthernetClass::schedule(void) stm32_eth_scheduler(); } -uint8_t *EthernetClass::MACAddressDefault(void) -{ - if ((mac_address[0] + mac_address[1] + mac_address[2] + mac_address[3] + mac_address[4] + mac_address[5]) == 0) { - uint32_t baseUID = *(uint32_t *)UID_BASE; - mac_address[0] = 0x00; - mac_address[1] = 0x80; - mac_address[2] = 0xE1; - mac_address[3] = (baseUID & 0x00FF0000) >> 16; - mac_address[4] = (baseUID & 0x0000FF00) >> 8; - mac_address[5] = (baseUID & 0x000000FF); - } - return mac_address; -} - void EthernetClass::MACAddress(uint8_t *mac) { mac_address[0] = mac[0]; diff --git a/src/STM32Ethernet.h b/src/STM32Ethernet.h index c567ff6..ad00608 100644 --- a/src/STM32Ethernet.h +++ b/src/STM32Ethernet.h @@ -18,7 +18,6 @@ class EthernetClass { IPAddress _dnsServerAddress; DhcpClass *_dhcp; uint8_t mac_address[6]; - uint8_t *MACAddressDefault(void); public: // Initialise the Ethernet with the internal provided MAC address and gain the rest of the diff --git a/src/utility/ethernetif.cpp b/src/utility/ethernetif.cpp index d254ece..fcb687f 100644 --- a/src/utility/ethernetif.cpp +++ b/src/utility/ethernetif.cpp @@ -96,6 +96,25 @@ __ALIGN_BEGIN uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END; /* Ethe static ETH_HandleTypeDef EthHandle; +/* If default MAC fields is not defined use default values based on UID */ +#if !defined(MAC_ADDR0) +#define MAC_ADDR0 0x00 +#endif +#if !defined(MAC_ADDR1) +#define MAC_ADDR1 0x80 +#endif +#if !defined(MAC_ADDR2) +#define MAC_ADDR2 0xE1 +#endif +#if !defined(MAC_ADDR3) +#define MAC_ADDR3 ((uint8_t)(((*(uint32_t *)UID_BASE) & 0x00FF0000) >> 16)) +#endif +#if !defined(MAC_ADDR4) +#define MAC_ADDR4 ((uint8_t)(((*(uint32_t *)UID_BASE) & 0x0000FF00) >> 8)) +#endif +#if !defined(MAC_ADDR5) +#define MAC_ADDR5 ((uint8_t)((*(uint32_t *)UID_BASE) & 0x000000FF)) +#endif static uint8_t macaddress[6] = { MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5 }; #if LWIP_IGMP From 348c968de150003a6e80cb61f43a72bf2f5ced43 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Wed, 11 Sep 2024 10:08:17 +0200 Subject: [PATCH 56/58] fix: align MAC address api with Arduino reference References: https://www.arduino.cc/reference/en/libraries/ethernet/ethernet.macaddress/ https://www.arduino.cc/reference/en/libraries/ethernet/ethernet.setmacaddress/ Pay attention that setMACAddress have to be called before Begin(). Else new MAC will be ignored. Fixes #81 Signed-off-by: Frederic Pillon --- README.md | 10 +++++----- keywords.txt | 2 ++ src/Dhcp.cpp | 8 ++++++-- src/STM32Ethernet.cpp | 21 +++++++-------------- src/STM32Ethernet.h | 5 ++--- src/utility/ethernetif.cpp | 14 +++++++++++++- src/utility/ethernetif.h | 1 + src/utility/stm32_eth.cpp | 19 +++++++++++++++++++ src/utility/stm32_eth.h | 2 ++ 9 files changed, 57 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index b87f2b2..0256ceb 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ extend the default one by adding some extra configuration in a file named `lwipo ## New alternative init procedure **!!!** -There are alternative inits of the Ethernetinterface with following orders: +There are alternative inits of the Ethernet interface with following orders: Ethernet.begin(); Ethernet.begin(ip); @@ -39,16 +39,16 @@ There are alternative inits of the Ethernetinterface with following orders: This is more logical. A MAC address is no more needed and will retrieved internally by the mbed MAC address! -You can get the MAC address with following function, this must done after Ethernet.Begin() +You can get the MAC address with following function, this must be done after Ethernet.Begin() uint8_t *mac; Ethernet.begin(); - mac = Ethernet.MACAddress(); + Ethernet.MACAddress(mac); -You can also set a new user based MAC address, this must done before Ethernet.begin() +You can also set a new user based MAC address, this must be done before Ethernet.begin() uint8_t newMAC[] = {0x00, 0x80, 0xE1, 0x01, 0x01, 0x01}; - Ethernet.MACAddress(newMAC); + Ethernet.setMACAddress(newMAC); Ethernet.begin(); ## Note diff --git a/keywords.txt b/keywords.txt index 09e494c..469aa86 100644 --- a/keywords.txt +++ b/keywords.txt @@ -38,9 +38,11 @@ localPort KEYWORD2 maintain KEYWORD2 linkStatus KEYWORD2 MACAddress KEYWORD2 +setMACAddress KEYWORD2 subnetMask KEYWORD2 gatewayIP KEYWORD2 dnsServerIP KEYWORD2 +setDnsServerIP KEYWORD2 setConnectionTimeout KEYWORD2 ####################################### diff --git a/src/Dhcp.cpp b/src/Dhcp.cpp index 1725e4f..19c7705 100644 --- a/src/Dhcp.cpp +++ b/src/Dhcp.cpp @@ -16,8 +16,12 @@ int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long // zero out _dhcpMacAddr memset(_dhcpMacAddr, 0, 6); reset_DHCP_lease(); - - memcpy((void *)_dhcpMacAddr, (void *)mac, 6); + if (mac == NULL) { + // use mac from Ethernet chip + stm32_eth_get_macaddr(_dhcpMacAddr); + } else { + memcpy((void *)_dhcpMacAddr, (void *)mac, 6); + } _dhcp_state = STATE_DHCP_START; stm32_set_DHCP_state(_dhcp_state); return request_DHCP_lease(); diff --git a/src/STM32Ethernet.cpp b/src/STM32Ethernet.cpp index 2a9aa3d..1e98284 100644 --- a/src/STM32Ethernet.cpp +++ b/src/STM32Ethernet.cpp @@ -8,7 +8,7 @@ int EthernetClass::begin(unsigned long timeout, unsigned long responseTimeout) stm32_eth_init(NULL, NULL, NULL, NULL); // Now try to get our config info from a DHCP server - int ret = _dhcp->beginWithDHCP(mac_address, timeout, responseTimeout); + int ret = _dhcp->beginWithDHCP(NULL, timeout, responseTimeout); if (ret == 1) { _dnsServerAddress = _dhcp->getDnsServerIp(); } @@ -58,7 +58,6 @@ int EthernetClass::begin(uint8_t *mac_address, unsigned long timeout, unsigned l if (ret == 1) { _dnsServerAddress = _dhcp->getDnsServerIp(); } - MACAddress(mac_address); return ret; } @@ -86,14 +85,13 @@ void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dn begin(mac_address, local_ip, dns_server, gateway, subnet); } -void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) +void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) { - stm32_eth_init(mac, local_ip.raw_address(), gateway.raw_address(), subnet.raw_address()); + stm32_eth_init(mac_address, local_ip.raw_address(), gateway.raw_address(), subnet.raw_address()); /* If there is a local DHCP informs it of our manual IP configuration to prevent IP conflict */ stm32_DHCP_manual_config(); _dnsServerAddress = dns_server; - MACAddress(mac); } EthernetLinkStatus EthernetClass::linkStatus() @@ -133,19 +131,14 @@ void EthernetClass::schedule(void) stm32_eth_scheduler(); } -void EthernetClass::MACAddress(uint8_t *mac) +void EthernetClass::setMACAddress(const uint8_t *mac_address) { - mac_address[0] = mac[0]; - mac_address[1] = mac[1]; - mac_address[2] = mac[2]; - mac_address[3] = mac[3]; - mac_address[4] = mac[4]; - mac_address[5] = mac[5]; + stm32_eth_set_macaddr(mac_address); } -uint8_t *EthernetClass::MACAddress(void) +void EthernetClass::MACAddress(uint8_t *mac_address) { - return mac_address; + stm32_eth_get_macaddr(mac_address); } IPAddress EthernetClass::localIP() diff --git a/src/STM32Ethernet.h b/src/STM32Ethernet.h index ad00608..f0ecfff 100644 --- a/src/STM32Ethernet.h +++ b/src/STM32Ethernet.h @@ -17,7 +17,6 @@ class EthernetClass { private: IPAddress _dnsServerAddress; DhcpClass *_dhcp; - uint8_t mac_address[6]; public: // Initialise the Ethernet with the internal provided MAC address and gain the rest of the @@ -42,13 +41,13 @@ class EthernetClass { int maintain(); void schedule(void); - void MACAddress(uint8_t *mac); - uint8_t *MACAddress(void); + void MACAddress(uint8_t *mac_address); IPAddress localIP(); IPAddress subnetMask(); IPAddress gatewayIP(); IPAddress dnsServerIP(); + void setMACAddress(const uint8_t *mac_address); void setDnsServerIP(const IPAddress dns_server); friend class EthernetClient; diff --git a/src/utility/ethernetif.cpp b/src/utility/ethernetif.cpp index fcb687f..9cb2695 100644 --- a/src/utility/ethernetif.cpp +++ b/src/utility/ethernetif.cpp @@ -627,11 +627,23 @@ __weak void ethernetif_notify_conn_changed(struct netif *netif) */ void ethernetif_set_mac_addr(const uint8_t *mac) { - if (mac != NULL) { + if ((mac != NULL) && !(ethernetif_is_init())) { memcpy(macaddress, mac, 6); } } +/** + * @brief This function get the current MAC address. + * @param mac: mac address + * @retval None + */ +void ethernetif_get_mac_addr(uint8_t *mac) +{ + if (mac != NULL) { + memcpy(mac, macaddress, 6); + } +} + #if LWIP_IGMP err_t igmp_mac_filter(struct netif *netif, const ip4_addr_t *ip4_addr, netif_mac_filter_action action) { diff --git a/src/utility/ethernetif.h b/src/utility/ethernetif.h index bab073e..ec7027b 100644 --- a/src/utility/ethernetif.h +++ b/src/utility/ethernetif.h @@ -61,6 +61,7 @@ void ethernetif_update_config(struct netif *netif); void ethernetif_notify_conn_changed(struct netif *netif); void ethernetif_set_mac_addr(const uint8_t *mac); +void ethernetif_get_mac_addr(uint8_t *mac); #if LWIP_IGMP err_t igmp_mac_filter(struct netif *netif, const ip4_addr_t *ip4_addr, netif_mac_filter_action action); diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index e1c9669..3a79595 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -268,6 +268,25 @@ uint8_t stm32_eth_is_init(void) return ethernetif_is_init(); } +/** + * @brief Set Ethernet MAC address + * @param mac: mac address + * @retval None + */ +void stm32_eth_set_macaddr(const uint8_t *mac) +{ + ethernetif_set_mac_addr(mac); +} +/** + * @brief Return Ethernet MAC address + * @param mac: mac address + * @retval None + */ +void stm32_eth_get_macaddr(uint8_t *mac) +{ + return ethernetif_get_mac_addr(mac); +} + /** * @brief Return Ethernet link status * @param None diff --git a/src/utility/stm32_eth.h b/src/utility/stm32_eth.h index d4c3ff2..753e06c 100644 --- a/src/utility/stm32_eth.h +++ b/src/utility/stm32_eth.h @@ -119,6 +119,8 @@ struct tcp_struct { /* Exported functions ------------------------------------------------------- */ void stm32_eth_init(const uint8_t *mac, const uint8_t *ip, const uint8_t *gw, const uint8_t *netmask); uint8_t stm32_eth_is_init(void); +void stm32_eth_get_macaddr(uint8_t *mac); +void stm32_eth_set_macaddr(const uint8_t *mac); uint8_t stm32_eth_link_up(void); void stm32_eth_scheduler(void); From cc8310f100c564a587669ba17d56483926780cf0 Mon Sep 17 00:00:00 2001 From: patricklaf Date: Thu, 27 Jun 2024 11:24:27 +0200 Subject: [PATCH 57/58] peek() function always return first byte of data Signed-off-by: patricklaf --- src/EthernetClient.cpp | 2 +- src/EthernetUdp.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EthernetClient.cpp b/src/EthernetClient.cpp index 9c71624..70bb01d 100644 --- a/src/EthernetClient.cpp +++ b/src/EthernetClient.cpp @@ -171,7 +171,7 @@ int EthernetClient::peek() if (!available()) { return -1; } - b = pbuf_get_at(_tcp_client->data.p, 0); + b = pbuf_get_at(_tcp_client->data.p, _tcp_client->data.p->tot_len - _tcp_client->data.available); return b; } diff --git a/src/EthernetUdp.cpp b/src/EthernetUdp.cpp index 78df02e..443f898 100644 --- a/src/EthernetUdp.cpp +++ b/src/EthernetUdp.cpp @@ -247,7 +247,7 @@ int EthernetUDP::peek() if (!_remaining) { return -1; } - b = pbuf_get_at(_udp.data.p, 0); + b = pbuf_get_at(_udp.data.p, _udp.data.p->tot_len - _udp.data.available); return b; } From b44edf68e1bb967b2a9df4b4e71c8d2e3ff70b0f Mon Sep 17 00:00:00 2001 From: TingRua zhang <68175738+q1098401179@users.noreply.github.com> Date: Fri, 7 Feb 2025 18:31:35 +0800 Subject: [PATCH 58/58] Update EthernetClient.cpp (#94) Signed-off-by: TingRua zhang <68175738+q1098401179@users.noreply.github.com> Co-authored-by: Frederic Pillon --- src/EthernetClient.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/EthernetClient.cpp b/src/EthernetClient.cpp index 70bb01d..5941afd 100644 --- a/src/EthernetClient.cpp +++ b/src/EthernetClient.cpp @@ -195,6 +195,7 @@ void EthernetClient::stop() tcp_connection_close(_tcp_client->pcb, _tcp_client); } mem_free(_tcp_client); + _tcp_client = NULL; } uint8_t EthernetClient::connected()