diff --git a/.github/workflows/Continuous-Integration.yml b/.github/workflows/Continuous-Integration.yml
new file mode 100644
index 0000000..259d70f
--- /dev/null
+++ b/.github/workflows/Continuous-Integration.yml
@@ -0,0 +1,69 @@
+name: STM32Ethernet Continuous Integration
+on:
+ push:
+ branches:
+ - main
+ 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@main
+
+ - name: Astyle check
+ id: Astyle
+ uses: stm32duino/actions/astyle-check@main
+
+ # Use the output from the `Astyle` step
+ - name: Astyle Errors
+ if: failure()
+ run: |
+ cat ${{ steps.Astyle.outputs.astyle-result }}
+ exit 1
+ codespell:
+ name: Check for spelling errors
+ runs-on: ubuntu-latest
+ steps:
+ - 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
+ steps:
+ # First of all, clone the repo using the checkout action.
+ - name: Checkout
+ uses: actions/checkout@main
+
+ - name: Compilation
+ id: Compile
+ uses: stm32duino/actions/compile-examples@main
+ with:
+ board-pattern: "DISCO_F746NG|NUCLEO_F429ZI|NUCLEO_F767ZI"
+ 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
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..0256ceb 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,34 @@ 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 **!!!**
+
+There are alternative inits of the Ethernet interface 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 be done after Ethernet.Begin()
+
+ uint8_t *mac;
+ Ethernet.begin();
+ Ethernet.MACAddress(mac);
+
+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.setMACAddress(newMAC);
+ Ethernet.begin();
## Note
@@ -39,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
diff --git a/examples/AdvancedChatServer/AdvancedChatServer.ino b/examples/AdvancedChatServer/AdvancedChatServer.ino
index e3719a6..451e9a9 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:
@@ -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) {
@@ -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 32516cd..13d06bc 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,10 +59,10 @@ 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:
+ // initialize the data ready and chip select pins:
pinMode(dataReadyPin, INPUT);
pinMode(chipSelectPin, OUTPUT);
@@ -131,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 8ee5126..cffbabf 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);
@@ -33,11 +33,11 @@ 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
- 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..d2561fb 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);
@@ -37,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:
@@ -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..3592889 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);
+ // try to configure using IP address instead of DHCP:
+ Ethernet.begin(ip);
}
// give the Ethernet shield a second to initialize:
delay(1000);
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/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..9030ee4 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());
@@ -55,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();
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
diff --git a/keywords.txt b/keywords.txt
index 1f19b2a..469aa86 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,9 +34,19 @@ remoteIP KEYWORD2
remotePort KEYWORD2
getSocketNumber KEYWORD2
localIP KEYWORD2
+localPort KEYWORD2
maintain KEYWORD2
+linkStatus KEYWORD2
+MACAddress KEYWORD2
+setMACAddress KEYWORD2
+subnetMask KEYWORD2
+gatewayIP KEYWORD2
+dnsServerIP KEYWORD2
+setDnsServerIP KEYWORD2
+setConnectionTimeout KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
-
+LinkON LITERAL1
+LinkOFF LITERAL1
diff --git a/library.json b/library.json
new file mode 100755
index 0000000..f8fe867
--- /dev/null
+++ b/library.json
@@ -0,0 +1,16 @@
+{
+ "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.4.0",
+ "frameworks": "arduino",
+ "platforms": "ststm32",
+ "build": {
+ "libArchive": false
+ }
+}
diff --git a/library.properties b/library.properties
index 0cbb04a..a7e954a 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=STM32duino STM32Ethernet
-version=1.0.3
+version=1.4.0
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
diff --git a/src/Dhcp.cpp b/src/Dhcp.cpp
index ac75c71..19c7705 100644
--- a/src/Dhcp.cpp
+++ b/src/Dhcp.cpp
@@ -1,129 +1,134 @@
-// 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();
+ 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();
+}
+
+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 f02c486..5941afd 100644
--- a/src/EthernetClient.cpp
+++ b/src/EthernetClient.cpp
@@ -1,5 +1,5 @@
extern "C" {
- #include "string.h"
+#include "string.h"
}
#include "Arduino.h"
@@ -9,20 +9,26 @@ 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);
}
-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;
@@ -33,27 +39,25 @@ int EthernetClient::connect(const char* host, uint16_t port) {
if (ret == 1) {
return connect(remote_addr, port);
} else {
- return ret;
- }
-}
-
-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));
+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;
}
@@ -61,17 +65,18 @@ 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)) {
+ 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) {
+ 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) >= _connectionTimeout)) {
stop();
return 0;
}
@@ -80,48 +85,70 @@ 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;
}
- 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;
- //Force to send data right now!
- if(ERR_OK != tcp_output(_tcp_client->pcb)) {
- return 0;
- }
+ do {
+ max_send_size = tcp_sndbuf(_tcp_client->pcb);
+ bytes_to_send = bytes_left > max_send_size ? max_send_size : bytes_left;
- stm32_eth_scheduler();
+ 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;
+ }
+ stm32_eth_scheduler();
+
+ } 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;
}
@@ -129,49 +156,58 @@ 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);
+ }
+ b = pbuf_get_at(_tcp_client->data.p, _tcp_client->data.p->tot_len - _tcp_client->data.available);
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);
}
+ mem_free(_tcp_client);
+ _tcp_client = NULL;
}
-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;
@@ -180,17 +216,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() {
- return _tcp_client != NULL;
+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 1cf73d8..5afb160 100644
--- a/src/EthernetClient.h
+++ b/src/EthernetClient.h
@@ -8,36 +8,62 @@
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();
+ 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);
+ };
+ void setConnectionTimeout(uint16_t timeout)
+ {
+ _connectionTimeout = timeout;
+ }
- friend class EthernetServer;
+ friend class EthernetServer;
- using Print::write;
+ using Print::write;
-private:
- struct tcp_struct *_tcp_client;
+ private:
+ struct tcp_struct *_tcp_client;
+ uint16_t _connectionTimeout = 10000;
};
#endif
diff --git a/src/EthernetServer.cpp b/src/EthernetServer.cpp
index f5353d8..2082498 100644
--- a/src/EthernetServer.cpp
+++ b/src/EthernetServer.cpp
@@ -9,24 +9,28 @@ extern "C" {
EthernetServer::EthernetServer(uint16_t port)
{
_port = port;
+ for (int i = 0; i < MAX_CLIENT; i++) {
+ _tcp_client[i] = {};
+ }
+ _tcp_server = {};
}
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;
@@ -36,17 +40,39 @@ void EthernetServer::begin()
tcp_accept(_tcp_server.pcb, tcp_accept_callback);
}
+void EthernetServer::begin(uint16_t port)
+{
+ _port = 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 */
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;
}
+ }
}
}
@@ -55,8 +81,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) {
@@ -83,10 +109,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);
@@ -97,3 +123,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 317bf41..10c306c 100644
--- a/src/EthernetServer.h
+++ b/src/EthernetServer.h
@@ -6,20 +6,23 @@
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);
- 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 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();
+ using Print::write;
};
#endif
diff --git a/src/EthernetUdp.cpp b/src/EthernetUdp.cpp
index c5ae45c..443f898 100644
--- a/src/EthernetUdp.cpp
+++ b/src/EthernetUdp.cpp
@@ -25,35 +25,55 @@
*
* 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) {
+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) {
+ if (_udp.pcb != NULL) {
return 0;
}
_udp.pcb = udp_new();
- if(_udp.pcb == NULL) {
+ if (_udp.pcb == NULL) {
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;
@@ -66,14 +86,15 @@ uint8_t EthernetUDP::begin(uint16_t port) {
/* 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;
@@ -100,15 +121,12 @@ 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;
}
- 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();
@@ -118,16 +136,12 @@ int EthernetUDP::beginPacket(IPAddress ip, uint16_t port)
int EthernetUDP::endPacket()
{
- if((_udp.pcb == NULL) || (_data == NULL)) {
- 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) {
+ if ((_udp.pcb == NULL) || (_data == NULL)) {
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;
}
@@ -146,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;
}
@@ -165,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;
@@ -181,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;
}
@@ -236,9 +244,10 @@ 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);
+ }
+ b = pbuf_get_at(_udp.data.p, _udp.data.p->tot_len - _udp.data.available);
return b;
}
@@ -250,6 +259,12 @@ 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 8d7d878..a9864cb 100644
--- a/src/EthernetUdp.h
+++ b/src/EthernetUdp.h
@@ -38,70 +38,82 @@
#define ethernetudp_h
#include
+#include
-extern "C" {
#include "utility/stm32_eth.h"
-}
#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
+ 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 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; };
+ // 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 0f806c5..1e98284 100644
--- a/src/STM32Ethernet.cpp
+++ b/src/STM32Ethernet.cpp
@@ -1,6 +1,51 @@
#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(NULL, NULL, NULL, NULL);
+
+ // Now try to get our config info from a DHCP server
+ int ret = _dhcp->beginWithDHCP(NULL, 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 same machine than gateway
+ begin(local_ip, subnet, gateway, gateway);
+}
+
+void EthernetClass::begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server)
+{
+ 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();
+ _dnsServerAddress = dns_server;
+}
+
int EthernetClass::begin(uint8_t *mac_address, unsigned long timeout, unsigned long responseTimeout)
{
static DhcpClass s_dhcp;
@@ -10,11 +55,9 @@ 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();
}
-
return ret;
}
@@ -42,22 +85,28 @@ 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;
}
-int EthernetClass::maintain(){
+EthernetLinkStatus EthernetClass::linkStatus()
+{
+ return (!stm32_eth_is_init()) ? Unknown : (stm32_eth_link_up() ? LinkON : LinkOFF);
+}
+
+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;
@@ -82,6 +131,16 @@ void EthernetClass::schedule(void)
stm32_eth_scheduler();
}
+void EthernetClass::setMACAddress(const uint8_t *mac_address)
+{
+ stm32_eth_set_macaddr(mac_address);
+}
+
+void EthernetClass::MACAddress(uint8_t *mac_address)
+{
+ stm32_eth_get_macaddr(mac_address);
+}
+
IPAddress EthernetClass::localIP()
{
return IPAddress(stm32_eth_get_ipaddr());
@@ -102,4 +161,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 78afbb7..f0ecfff 100644
--- a/src/STM32Ethernet.h
+++ b/src/STM32Ethernet.h
@@ -7,29 +7,51 @@
#include "EthernetServer.h"
#include "Dhcp.h"
+enum EthernetLinkStatus {
+ Unknown,
+ LinkON,
+ LinkOFF
+};
+
class EthernetClass {
-private:
- IPAddress _dnsServerAddress;
- DhcpClass* _dhcp;
-public:
- // 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);
-
- IPAddress localIP();
- IPAddress subnetMask();
- IPAddress gatewayIP();
- IPAddress dnsServerIP();
-
- friend class EthernetClient;
- friend class EthernetServer;
+ private:
+ IPAddress _dnsServerAddress;
+ DhcpClass *_dhcp;
+
+ 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_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;
+ friend class EthernetServer;
};
extern EthernetClass Ethernet;
diff --git a/src/lwipopts.h b/src/lwipopts.h
index 56f805b..0cf3278 100644
--- a/src/lwipopts.h
+++ b/src/lwipopts.h
@@ -1,18 +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
-#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 7a988f5..f605098 100644
--- a/src/lwipopts_default.h
+++ b/src/lwipopts_default.h
@@ -1,249 +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.
- *
- * 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 __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
-
-/* ---------- 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
-
-/* Controls if TCP should queue segments that arrive out of
- order. Define to 0 if your device is low on memory. */
-#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 (2*TCP_MSS)
-
-
-/* ---------- ICMP options ---------- */
-#define LWIP_ICMP 1
-
-
-/* ---------- DHCP options ---------- */
-#define LWIP_DHCP 1
-
-/* ---------- DNS options ---------- */
-#define LWIP_DNS 1
-
-
-/* ---------- UDP options ---------- */
-#define LWIP_UDP 1
-#define UDP_TTL 255
-
-
-/* ---------- Statistics options ---------- */
-#define LWIP_STATS 0
-
-/* ---------- link callback options ---------- */
-/* LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface
- * whenever the link changes (i.e., link down)
- */
-#define LWIP_NETIF_LINK_CALLBACK 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
-
-/*
- ------------------------------------
- ---------- 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 simultaneously 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 simultaneously 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.c b/src/utility/ethernetif.cpp
similarity index 76%
rename from src/utility/ethernetif.c
rename to src/utility/ethernetif.cpp
index eeb966c..9cb2695 100644
--- a/src/utility/ethernetif.c
+++ b/src/utility/ethernetif.cpp
@@ -1,643 +1,738 @@
-/**
- ******************************************************************************
- * @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 "stm32_eth.h"
-#include "variant.h"
-
-#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 };
-
-/* 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);
-
- /**** 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 );
-}
-
-/**
- * @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 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) {
- 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);
- }
-}
-
-#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'
+
+/* 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 */
+#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;
+
+/* 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
+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 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)
+{
+ 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)
+{
+ uint32_t regvalue = 0;
+
+ if (netif_is_link_up(netif)) {
+ /* Restart the auto-negotiation */
+ if (EthHandle.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE) {
+
+ /* 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) {
+ /* 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) && !(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)
+{
+ 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
index e851c19..ec7027b 100644
--- a/src/utility/ethernetif.h
+++ b/src/utility/ethernetif.h
@@ -1,71 +1,75 @@
-/**
- ******************************************************************************
- * @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__
-
-#include "lwip/err.h"
-#include "lwip/netif.h"
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-/* Exported types ------------------------------------------------------------*/
-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);
-
-#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);
+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);
+void register_multicast_address(const uint8_t *mac);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/utility/stm32_eth.c b/src/utility/stm32_eth.cpp
similarity index 71%
rename from src/utility/stm32_eth.c
rename to src/utility/stm32_eth.cpp
index 4365b17..3a79595 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
@@ -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
@@ -67,10 +63,17 @@
* 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
+/* 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;
@@ -96,37 +99,41 @@ 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;
+#if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100)
+ /* Handler for stimer */
+ static stimer_t TimHandle;
+#else
+ HardwareTimer *EthTim = NULL;
+#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(stimer_t *htim);
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
+* @brief Configure the network interface
* @param None
* @retval None
*/
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);
/* 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);
}
@@ -139,15 +146,24 @@ static void Netif_Config(void)
/**
* @brief Scheduler callback. Call by a timer interrupt.
-* @param htim: pointer to stimer_t
+* @param htim: pointer to stimer_t or Hardware Timer
* @retval None
*/
-static void scheduler_callback(stimer_t *htim)
+#if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100)
+ static void scheduler_callback(stimer_t *htim)
+#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);
- stm32_eth_scheduler();
+#endif
+ _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.
@@ -158,61 +174,80 @@ 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.
+* @param None
+* @retval None
+*/
+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 */
+ EthTim->setOverflow(1000, MICROSEC_FORMAT);
+ 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)
{
static uint8_t initDone = 0;
- if(!initDone) {
+ 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 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 (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(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 (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(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 (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 */
+ }
- /* 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;
}
@@ -224,11 +259,72 @@ void stm32_eth_init(const uint8_t *mac, const uint8_t *ip, const uint8_t *gw, co
}
/**
- * @brief This function must be called in main loop in standalone mode.
+ * @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 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
+ * @retval 1 for link up, 0 for link down
+ */
+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) {
+void stm32_eth_scheduler(void)
+{
+ if (EthTim != NULL) {
+ EthTim->refresh();
+ }
+}
+
+/**
+ * @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 */
#ifndef ETH_INPUT_USE_IT
@@ -236,7 +332,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();
}
@@ -256,7 +352,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;
}
@@ -265,63 +362,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;
- /* DHCP timeout */
- if (dhcp->tries > MAX_DHCP_TRIES)
- {
- DHCP_state = DHCP_TIMEOUT;
+ 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);
- // If DHCP address not bind, keep DHCP stopped
- DHCP_Started_by_user = 0;
+ /* DHCP timeout */
+ if (dhcp->tries > MAX_DHCP_TRIES) {
+ DHCP_state = DHCP_TIMEOUT;
- /* Stop DHCP */
- dhcp_stop(netif);
+ // If DHCP address not bind, keep DHCP stopped
+ DHCP_Started_by_user = 0;
+
+ /* 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;
@@ -336,8 +425,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);
@@ -349,7 +437,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);
}
@@ -358,13 +447,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;
}
@@ -376,7 +466,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;
}
@@ -392,7 +483,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;
}
@@ -403,7 +495,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));
}
@@ -412,7 +505,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));
}
@@ -421,7 +515,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));
}
@@ -430,7 +525,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);
}
@@ -440,7 +536,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));
}
@@ -454,49 +551,39 @@ uint32_t stm32_eth_get_dhcpaddr(void) {
*/
void ethernetif_notify_conn_changed(struct netif *netif)
{
- if(netif_is_link_up(netif))
- {
- printf("Link up\n");
-
+ 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;
}
/* When the netif link is down this function must be called.*/
netif_set_down(netif);
-
- printf("Link down\n");
}
}
#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
*/
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;
}
}
@@ -514,9 +601,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);
}
}
@@ -532,7 +619,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;
@@ -556,38 +643,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;
@@ -603,7 +690,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;
}
@@ -627,12 +714,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);
@@ -644,9 +731,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;
@@ -669,10 +756,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;
@@ -691,31 +778,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);
}
@@ -725,7 +812,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);
}
@@ -750,9 +837,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);
}
@@ -761,6 +848,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);
}
@@ -773,7 +864,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
*/
@@ -781,10 +872,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 */
@@ -797,17 +886,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);
}
@@ -830,26 +915,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) {
+ /* Looking for an empty socket */
+ 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);
@@ -871,9 +955,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);
@@ -893,7 +975,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)
{
@@ -901,31 +983,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);
}
@@ -933,8 +1009,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);
@@ -959,8 +1034,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;
}
@@ -981,8 +1055,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;
}
@@ -1000,7 +1074,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);
@@ -1012,7 +1086,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 bf1bb28..753e06c 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,18 +45,18 @@
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip/opt.h"
+#include
/* 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 {
@@ -74,6 +70,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 */
@@ -115,33 +112,37 @@ struct tcp_struct {
#define MAX_CLIENT 32
#ifdef ETH_INPUT_USE_IT
-extern struct netif gnetif;
+ extern struct netif gnetif;
#endif
/* 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);
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
@@ -165,15 +166,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"
-#endif
-
-#ifdef __cplusplus
-}
+ #error "LWIP_TCP must be enabled in lwipopts.h"
#endif
#endif /* __STM32_ETH_H__ */