From 4984100f485fb3a3d5f9ea28fc1fa0dd289e05f7 Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Thu, 3 Dec 2020 09:07:27 +0100 Subject: [PATCH 01/12] HardwareTimer: remove usage of TIMER_OUTPUT_COMPARE mode With introduction of PR https://github.com/stm32duino/Arduino_Core_STM32/pull/1247 Usage of TIMER_OUTPUT_COMPARE becomes obsolete. Note: removing setMode(1, TIMER_OUTPUT_COMPARE) also works before PR #1247. Signed-off-by: Alexandre Bourdiol --- src/utility/stm32_eth.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index 28ad2ba..22b3fa7 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -176,7 +176,6 @@ static void TIM_scheduler_Config(void) { /* Configure HardwareTimer */ HardwareTimer *EthTim = new HardwareTimer(DEFAULT_ETHERNET_TIMER); - EthTim->setMode(1, TIMER_OUTPUT_COMPARE); /* Timer set to 1ms */ EthTim->setOverflow(1000, MICROSEC_FORMAT); From ea18d121f02db38899a01aec32a9c87944ded073 Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Thu, 3 Dec 2020 09:46:17 +0100 Subject: [PATCH 02/12] Run astyle Fix astyle issue Signed-off-by: Alexandre Bourdiol --- src/lwipopts.h | 10 +++---- src/lwipopts_default.h | 56 +++++++++++++++++++------------------- src/utility/ethernetif.cpp | 2 +- src/utility/stm32_eth.cpp | 14 +++++----- src/utility/stm32_eth.h | 32 +++++++++++----------- 5 files changed, 57 insertions(+), 57 deletions(-) diff --git a/src/lwipopts.h b/src/lwipopts.h index 09bcbde..0cf3278 100644 --- a/src/lwipopts.h +++ b/src/lwipopts.h @@ -9,12 +9,12 @@ /* LwIP specific configuration options. */ #if __has_include("STM32lwipopts.h") -#include "STM32lwipopts.h" + #include "STM32lwipopts.h" #else -#if __has_include("lwipopts_extra.h") -#include "lwipopts_extra.h" -#endif -#include "lwipopts_default.h" + #if __has_include("lwipopts_extra.h") + #include "lwipopts_extra.h" + #endif + #include "lwipopts_default.h" #endif #endif /* _ARDUINO_LWIPOPTS_H */ diff --git a/src/lwipopts_default.h b/src/lwipopts_default.h index f13b274..d7fae2d 100644 --- a/src/lwipopts_default.h +++ b/src/lwipopts_default.h @@ -151,35 +151,35 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums #ifdef CHECKSUM_BY_HARDWARE -/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/ -#define CHECKSUM_GEN_IP 0 -/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/ -#define CHECKSUM_GEN_UDP 0 -/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/ -#define CHECKSUM_GEN_TCP 0 -/* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/ -#define CHECKSUM_CHECK_IP 0 -/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/ -#define CHECKSUM_CHECK_UDP 0 -/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/ -#define CHECKSUM_CHECK_TCP 0 -/* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/ -#define CHECKSUM_GEN_ICMP 0 + /* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/ + #define CHECKSUM_GEN_IP 0 + /* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/ + #define CHECKSUM_GEN_UDP 0 + /* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/ + #define CHECKSUM_GEN_TCP 0 + /* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/ + #define CHECKSUM_CHECK_IP 0 + /* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/ + #define CHECKSUM_CHECK_UDP 0 + /* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/ + #define CHECKSUM_CHECK_TCP 0 + /* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/ + #define CHECKSUM_GEN_ICMP 0 #else -/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/ -#define CHECKSUM_GEN_IP 1 -/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/ -#define CHECKSUM_GEN_UDP 1 -/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/ -#define CHECKSUM_GEN_TCP 1 -/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/ -#define CHECKSUM_CHECK_IP 1 -/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/ -#define CHECKSUM_CHECK_UDP 1 -/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/ -#define CHECKSUM_CHECK_TCP 1 -/* CHECKSUM_CHECK_ICMP==1: Check checksums by hardware for incoming ICMP packets.*/ -#define CHECKSUM_GEN_ICMP 1 + /* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/ + #define CHECKSUM_GEN_IP 1 + /* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/ + #define CHECKSUM_GEN_UDP 1 + /* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/ + #define CHECKSUM_GEN_TCP 1 + /* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/ + #define CHECKSUM_CHECK_IP 1 + /* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/ + #define CHECKSUM_CHECK_UDP 1 + /* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/ + #define CHECKSUM_CHECK_TCP 1 + /* CHECKSUM_CHECK_ICMP==1: Check checksums by hardware for incoming ICMP packets.*/ + #define CHECKSUM_GEN_ICMP 1 #endif diff --git a/src/utility/ethernetif.cpp b/src/utility/ethernetif.cpp index 31aa806..d254ece 100644 --- a/src/utility/ethernetif.cpp +++ b/src/utility/ethernetif.cpp @@ -54,7 +54,7 @@ #include "lwip/igmp.h" #include "stm32_eth.h" #if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01050000) -#include "variant.h" + #include "variant.h" #endif #ifdef __cplusplus diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index 22b3fa7..1148ab0 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -63,8 +63,8 @@ * They could be used for this library when available */ #ifndef DEFAULT_ETHERNET_TIMER -#define DEFAULT_ETHERNET_TIMER TIM14 -#warning "Default timer used to call ethernet scheduler at regular interval: TIM14" + #define DEFAULT_ETHERNET_TIMER TIM14 + #warning "Default timer used to call ethernet scheduler at regular interval: TIM14" #endif /* Ethernet configuration: user parameters */ @@ -93,8 +93,8 @@ static uint8_t DHCP_Started_by_user = 0; static uint32_t gEhtLinkTickStart = 0; #if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100) -/* Handler for stimer */ -static stimer_t TimHandle; + /* Handler for stimer */ + static stimer_t TimHandle; #endif /*************************** Function prototype *******************************/ @@ -137,11 +137,11 @@ static void Netif_Config(void) * @retval None */ #if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100) -static void scheduler_callback(stimer_t *htim) + static void scheduler_callback(stimer_t *htim) #elif (STM32_CORE_VERSION <= 0x01080000) -static void scheduler_callback(HardwareTimer *htim) + static void scheduler_callback(HardwareTimer *htim) #else -static void scheduler_callback(void) + static void scheduler_callback(void) #endif { #if (STM32_CORE_VERSION <= 0x01080000) diff --git a/src/utility/stm32_eth.h b/src/utility/stm32_eth.h index 4866be6..d4c3ff2 100644 --- a/src/utility/stm32_eth.h +++ b/src/utility/stm32_eth.h @@ -112,7 +112,7 @@ struct tcp_struct { #define MAX_CLIENT 32 #ifdef ETH_INPUT_USE_IT -extern struct netif gnetif; + extern struct netif gnetif; #endif @@ -125,22 +125,22 @@ void stm32_eth_scheduler(void); void User_notification(struct netif *netif); #if LWIP_DHCP -void stm32_DHCP_Process(struct netif *netif); -void stm32_DHCP_Periodic_Handle(struct netif *netif); -void stm32_DHCP_manual_config(void); -uint8_t stm32_get_DHCP_lease_state(void); -void stm32_set_DHCP_state(uint8_t state); -uint8_t stm32_get_DHCP_state(void); -uint8_t stm32_dhcp_started(void); + void stm32_DHCP_Process(struct netif *netif); + void stm32_DHCP_Periodic_Handle(struct netif *netif); + void stm32_DHCP_manual_config(void); + uint8_t stm32_get_DHCP_lease_state(void); + void stm32_set_DHCP_state(uint8_t state); + uint8_t stm32_get_DHCP_state(void); + uint8_t stm32_dhcp_started(void); #else -#error "LWIP_DHCP must be enabled in lwipopts.h" + #error "LWIP_DHCP must be enabled in lwipopts.h" #endif #if LWIP_DNS -void stm32_dns_init(const uint8_t *dnsaddr); -int8_t stm32_dns_gethostbyname(const char *hostname, uint32_t *ipaddr); + void stm32_dns_init(const uint8_t *dnsaddr); + int8_t stm32_dns_gethostbyname(const char *hostname, uint32_t *ipaddr); #else -#error "LWIP_DNS must be enabled in lwipopts.h" + #error "LWIP_DNS must be enabled in lwipopts.h" #endif #if LWIP_UDP @@ -164,11 +164,11 @@ ip_addr_t *u8_to_ip_addr(uint8_t *ipu8, ip_addr_t *ipaddr); uint32_t ip_addr_to_u32(ip_addr_t *ipaddr); #if LWIP_TCP -err_t tcp_connected_callback(void *arg, struct tcp_pcb *tpcb, err_t err); -err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err); -void tcp_connection_close(struct tcp_pcb *tpcb, struct tcp_struct *tcp); + err_t tcp_connected_callback(void *arg, struct tcp_pcb *tpcb, err_t err); + err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err); + void tcp_connection_close(struct tcp_pcb *tpcb, struct tcp_struct *tcp); #else -#error "LWIP_TCP must be enabled in lwipopts.h" + #error "LWIP_TCP must be enabled in lwipopts.h" #endif #endif /* __STM32_ETH_H__ */ From a1f708d4a6937abd05f13084620dbcc07948986f Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 5 Oct 2021 18:37:56 +0200 Subject: [PATCH 03/12] ci: change to main branch Signed-off-by: Frederic Pillon --- .github/workflows/Continuous-Integration.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/Continuous-Integration.yml b/.github/workflows/Continuous-Integration.yml index 982a286..0547884 100644 --- a/.github/workflows/Continuous-Integration.yml +++ b/.github/workflows/Continuous-Integration.yml @@ -2,7 +2,7 @@ name: STM32Ethernet Continuous Integration on: push: branches: - - master + - main paths-ignore: - '*' - '**.md' @@ -19,11 +19,11 @@ jobs: steps: # First of all, clone the repo using the checkout action. - name: Checkout - uses: actions/checkout@master + uses: actions/checkout@main - name: Astyle check id: Astyle - uses: stm32duino/actions/astyle-check@master + uses: stm32duino/actions/astyle-check@main # Use the output from the `Astyle` step - name: Astyle Errors @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest name: Spell check steps: - - uses: actions/checkout@master + - uses: actions/checkout@main - uses: arduino/actions/libraries/spell-check@master # with: # ignore-words-list: "./extras/codespell-ignore-words-list.txt" @@ -45,11 +45,11 @@ jobs: steps: # First of all, clone the repo using the checkout action. - name: Checkout - uses: actions/checkout@master + uses: actions/checkout@main - name: Compilation id: Compile - uses: stm32duino/actions/compile-examples@master + uses: stm32duino/actions/compile-examples@main with: board-pattern: "DISCO_F746NG|NUCLEO_F429ZI|NUCLEO_F767ZI" libraries: "STM32duino LwIP" From abcf362a8438d4f79ec705babe71c162b232940f Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Mon, 28 Feb 2022 16:33:04 +0100 Subject: [PATCH 04/12] ci: add library STM32duino FreeRTOS --- .github/workflows/Continuous-Integration.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Continuous-Integration.yml b/.github/workflows/Continuous-Integration.yml index 0547884..b324ceb 100644 --- a/.github/workflows/Continuous-Integration.yml +++ b/.github/workflows/Continuous-Integration.yml @@ -52,11 +52,11 @@ jobs: uses: stm32duino/actions/compile-examples@main with: board-pattern: "DISCO_F746NG|NUCLEO_F429ZI|NUCLEO_F767ZI" - libraries: "STM32duino LwIP" + libraries: "STM32duino LwIP, STM32duino FreeRTOS" # Use the output from the `Compile` step - name: Compilation Errors if: failure() run: | cat ${{ steps.Compile.outputs.compile-result }} - exit 1 \ No newline at end of file + exit 1 From 7669880d8f1347b45f4bc2749ce9ef3eaf2b40ba Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Fri, 25 Feb 2022 18:19:01 +0100 Subject: [PATCH 05/12] feat: Add examples to demonstrate how to use FreeRTOS with Ethernet Both WebClientFreeRTOS and WebServerFreeRTOS are available. Warning: FreeRTOS may disable interrupts between xTaskCreate() and vTaskStartScheduler(). Thus Ethernet, which is using Interrupts, should be initialized after scheduling start. thus it is done within a task. Fixes #36 Signed-off-by: Alexandre Bourdiol --- .../WebClientFreeRTOS/WebClientFreeRTOS.ino | 104 +++++++++++++ .../WebServerFreeRTOS/WebServerFreeRTOS.ino | 139 ++++++++++++++++++ 2 files changed, 243 insertions(+) create mode 100644 examples/WebClientFreeRTOS/WebClientFreeRTOS.ino create mode 100644 examples/WebServerFreeRTOS/WebServerFreeRTOS.ino diff --git a/examples/WebClientFreeRTOS/WebClientFreeRTOS.ino b/examples/WebClientFreeRTOS/WebClientFreeRTOS.ino new file mode 100644 index 0000000..842f244 --- /dev/null +++ b/examples/WebClientFreeRTOS/WebClientFreeRTOS.ino @@ -0,0 +1,104 @@ +/* + Port of WebClient on FreeRTOS + + This sketch connects to a website (http://www.google.com) + + Circuit: + * STM32 board with Ethernet support + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe, based on work by Adrian McEwen + modified 23 Jun 2017 + by Wi6Labs + modified 1 Jun 2018 + by sstaub + */ + +#include +#include +#include + +// if you don't want to use DNS (and reduce your sketch size) +// use the numeric IP instead of the name for the server: +//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS) +char server[] = "www.google.com"; // name address for Google (using DNS) + +// Set the static IP address to use if the DHCP fails to assign +IPAddress ip(192, 168, 0, 177); + +// Initialize the Ethernet client library +// with the IP address and port of the server +// that you want to connect to (port 80 is default for HTTP): +EthernetClient client; + + +// task code +void taskETH(void* arg) { + UNUSED(arg); + // start the Ethernet connection: + if (Ethernet.begin() == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // try to configure using IP address instead of DHCP: + Ethernet.begin(ip); + } + // give the Ethernet shield a second to initialize: + delay(1000); + Serial.println("connecting..."); + + // if you get a connection, report back via serial: + if (client.connect(server, 80)) { + Serial.println("connected"); + // Make a HTTP request: + client.println("GET /search?q=arduino HTTP/1.1"); + client.println("Host: www.google.com"); + client.println("Connection: close"); + client.println(); + } else { + // if you didn't get a connection to the server: + Serial.println("connection failed"); + } + + while(1){ + // if there are incoming bytes available + // from the server, read them and print them: + if (client.available()) { + char c = client.read(); + Serial.print(c); + } + + // if the server's disconnected, stop the client: + if (!client.connected()) { + Serial.println(); + Serial.println("disconnecting."); + client.stop(); + + // do nothing forevermore: + while (true); + } + } +} + + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + portBASE_TYPE s = xTaskCreate(taskETH, NULL, 200, NULL, 1, NULL); + if (s != pdPASS) { + printf("Ethernet task creation failed\n"); + while (1); + } + + vTaskStartScheduler(); + Serial.println("Scheduler failed"); + while (1); +} + +void loop() { + // Not used. +} diff --git a/examples/WebServerFreeRTOS/WebServerFreeRTOS.ino b/examples/WebServerFreeRTOS/WebServerFreeRTOS.ino new file mode 100644 index 0000000..f69b68b --- /dev/null +++ b/examples/WebServerFreeRTOS/WebServerFreeRTOS.ino @@ -0,0 +1,139 @@ +/* + Port of WebServer on FreeRTOS + + A simple web server that shows the value of the analog input pins. + 2 task are created: + Ethernet: to manage the server + Analog to read input values + + Circuit: + STM32 board with Ethernet support + Analog inputs attached to pins A0 through A5 (optional) + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe + modified 02 Sept 2015 + by Arturo Guadalupi + modified 23 Jun 2017 + by Wi6Labs + modified 1 Jun 2018 + by sstaub +*/ + +#include +#include +#include + +// Enter an IP address for your controller below. +// The IP address will be dependent on your local network: +IPAddress ip(192, 168, 0, 177); + +// Initialize the Ethernet server library +// with the IP address and port you want to use +// (port 80 is default for HTTP): +EthernetServer server(80); + +#define ANALOG_CHANEL_NUMBER 6 +int sensorReading[ANALOG_CHANEL_NUMBER]; + +void taskAnalog(void* arg) { + UNUSED(arg); + while (1) { + for (int analogChannel = 0; analogChannel < ANALOG_CHANEL_NUMBER; analogChannel++) { + sensorReading[analogChannel] = analogRead(analogChannel); + } + vTaskDelay(1000); // read Analog every seconds + } +} + +// task code +void taskETH(void* arg) { + UNUSED(arg); + // start the Ethernet connection and the server: + Ethernet.begin(ip); + server.begin(); + Serial.print("server is at "); + Serial.println(Ethernet.localIP()); + + while (1) { + // listen for incoming clients + EthernetClient client = server.available(); + if (client) { + Serial.println("new client"); + // an http request ends with a blank line + bool currentLineIsBlank = true; + while (client.connected()) { + if (client.available()) { + char c = client.read(); + Serial.write(c); + // if you've gotten to the end of the line (received a newline + // character) and the line is blank, the http request has ended, + // so you can send a reply + if (c == '\n' && currentLineIsBlank) { + // send a standard http response header + client.println("HTTP/1.1 200 OK"); + client.println("Content-Type: text/html"); + client.println("Connection: close"); // the connection will be closed after completion of the response + client.println("Refresh: 5"); // refresh the page automatically every 5 sec + client.println(); + client.println(""); + client.println(""); + // output the value of each analog input pin + for (int analogChannel = 0; analogChannel < ANALOG_CHANEL_NUMBER; analogChannel++) { + client.print("analog input "); + client.print(analogChannel); + client.print(" is "); + client.print(sensorReading[analogChannel]); + client.println("
"); + } + client.println(""); + break; + } + if (c == '\n') { + // you're starting a new line + currentLineIsBlank = true; + } else if (c != '\r') { + // you've gotten a character on the current line + currentLineIsBlank = false; + } + } + } + // give the web browser time to receive the data + delay(1); + // close the connection: + client.stop(); + Serial.println("client disconnected"); + } + } +} + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + portBASE_TYPE s = xTaskCreate(taskETH, NULL, 200, NULL, 1, NULL); + if (s != pdPASS) { + printf("Ethernet task creation failed\n"); + while (1); + } + + s = xTaskCreate(taskAnalog, NULL, 200, NULL, 2, NULL); + if (s != pdPASS) { + printf("Analog task creation failed\n"); + while (1); + } + + vTaskStartScheduler(); + Serial.println("Scheduler failed"); + while (1); +} + + +void loop() { + // Not used. +} \ No newline at end of file From c191eade02474154318584b9d0726d8a818e3a2a Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Tue, 1 Mar 2022 16:49:23 +0100 Subject: [PATCH 06/12] fix: Assume DNS is the same IP than gateway When DNS is not provided, it is more likely to be the same than gateway (more likely than xx.xx.xx.1) Signed-off-by: Alexandre Bourdiol --- src/STM32Ethernet.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/STM32Ethernet.cpp b/src/STM32Ethernet.cpp index 77313a6..a0753de 100644 --- a/src/STM32Ethernet.cpp +++ b/src/STM32Ethernet.cpp @@ -33,11 +33,8 @@ void EthernetClass::begin(IPAddress local_ip, IPAddress subnet) void EthernetClass::begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway) { - // Assume the DNS server will be the machine on the same network as the local IP - // but with last octet being '1' - IPAddress dns_server = local_ip; - dns_server[3] = 1; - begin(local_ip, subnet, gateway, dns_server); + // Assume the DNS server will be the same machine than gateway + begin(local_ip, subnet, gateway, gateway); } void EthernetClass::begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server) From d5993db2dc7c13d682418d409c03cb7f91fb64e5 Mon Sep 17 00:00:00 2001 From: Solariseir Date: Fri, 11 Mar 2022 11:29:01 +0100 Subject: [PATCH 07/12] fix: if DHCP fails the static IP can be applied without problem (#50) and adding timeout to client connection Co-authored-by: Alexandre Bourdiol <50730894+ABOSTM@users.noreply.github.com> Co-authored-by: Frederic Pillon --- src/EthernetClient.cpp | 5 ++-- src/EthernetClient.h | 5 ++++ src/utility/stm32_eth.cpp | 51 +++++++++++++++++++++------------------ 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/EthernetClient.cpp b/src/EthernetClient.cpp index 5db2e47..4fd0a7f 100644 --- a/src/EthernetClient.cpp +++ b/src/EthernetClient.cpp @@ -65,6 +65,7 @@ int EthernetClient::connect(IPAddress ip, uint16_t port) _tcp_client->data.available = 0; _tcp_client->state = TCP_NONE; + uint32_t startTime = millis(); ip_addr_t ipaddr; tcp_arg(_tcp_client->pcb, _tcp_client); if (ERR_OK != tcp_connect(_tcp_client->pcb, u8_to_ip_addr(rawIPAddress(ip), &ipaddr), port, &tcp_connected_callback)) { @@ -72,10 +73,10 @@ int EthernetClient::connect(IPAddress ip, uint16_t port) return 0; } - uint32_t startTime = millis(); + startTime = millis(); while (_tcp_client->state == TCP_NONE) { stm32_eth_scheduler(); - if ((_tcp_client->state == TCP_CLOSING) || ((millis() - startTime) >= 10000)) { + if ((_tcp_client->state == TCP_CLOSING) || ((millis() - startTime) >= _timeout)) { stop(); return 0; } diff --git a/src/EthernetClient.h b/src/EthernetClient.h index 251b580..c937a05 100644 --- a/src/EthernetClient.h +++ b/src/EthernetClient.h @@ -52,6 +52,10 @@ class EthernetClient : public Client { { return (_tcp_client->pcb->remote_port); }; + void setTimeout(uint16_t timeout) + { + _timeout = timeout; + } friend class EthernetServer; @@ -59,6 +63,7 @@ class EthernetClient : public Client { private: struct tcp_struct *_tcp_client; + uint16_t _timeout = 10000; }; #endif diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index 1148ab0..73c49a0 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -111,6 +111,7 @@ static void TIM_scheduler_Config(void); */ static void Netif_Config(void) { + netif_remove(&gnetif); /* Add the network interface */ netif_add(&gnetif, &(gconfig.ipaddr), &(gconfig.netmask), &(gconfig.gw), NULL, ðernetif_init, ðernet_input); @@ -176,6 +177,7 @@ static void TIM_scheduler_Config(void) { /* Configure HardwareTimer */ HardwareTimer *EthTim = new HardwareTimer(DEFAULT_ETHERNET_TIMER); + EthTim->setMode(1, TIMER_OUTPUT_COMPARE); /* Timer set to 1ms */ EthTim->setOverflow(1000, MICROSEC_FORMAT); @@ -191,47 +193,48 @@ void stm32_eth_init(const uint8_t *mac, const uint8_t *ip, const uint8_t *gw, co if (!initDone) { /* Initialize the LwIP stack */ lwip_init(); + } - if (mac != NULL) { - ethernetif_set_mac_addr(mac); - } // else default value is used: MAC_ADDR0 ... MAC_ADDR5 + if (mac != NULL) { + ethernetif_set_mac_addr(mac); + } // else default value is used: MAC_ADDR0 ... MAC_ADDR5 - if (ip != NULL) { - IP_ADDR4(&(gconfig.ipaddr), ip[0], ip[1], ip[2], ip[3]); - } else { + if (ip != NULL) { + IP_ADDR4(&(gconfig.ipaddr), ip[0], ip[1], ip[2], ip[3]); + } else { #if LWIP_DHCP - ip_addr_set_zero_ip4(&(gconfig.ipaddr)); + ip_addr_set_zero_ip4(&(gconfig.ipaddr)); #else - IP_ADDR4(&(gconfig.ipaddr), IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); + IP_ADDR4(&(gconfig.ipaddr), IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); #endif /* LWIP_DHCP */ - } + } - if (gw != NULL) { - IP_ADDR4(&(gconfig.gw), gw[0], gw[1], gw[2], gw[3]); - } else { + if (gw != NULL) { + IP_ADDR4(&(gconfig.gw), gw[0], gw[1], gw[2], gw[3]); + } else { #if LWIP_DHCP - ip_addr_set_zero_ip4(&(gconfig.gw)); + ip_addr_set_zero_ip4(&(gconfig.gw)); #else - IP_ADDR4(&(gconfig.gw), GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + IP_ADDR4(&(gconfig.gw), GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); #endif /* LWIP_DHCP */ - } + } - if (netmask != NULL) { - IP_ADDR4(&(gconfig.netmask), netmask[0], netmask[1], netmask[2], netmask[3]); - } else { + if (netmask != NULL) { + IP_ADDR4(&(gconfig.netmask), netmask[0], netmask[1], netmask[2], netmask[3]); + } else { #if LWIP_DHCP - ip_addr_set_zero_ip4(&(gconfig.netmask)); + ip_addr_set_zero_ip4(&(gconfig.netmask)); #else - IP_ADDR4(&(gconfig.netmask), NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); + IP_ADDR4(&(gconfig.netmask), NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); #endif /* LWIP_DHCP */ - } + } - /* Configure the Network interface */ - Netif_Config(); + /* Configure the Network interface */ + Netif_Config(); + if (!initDone) { // stm32_eth_scheduler() will be called every 1ms. TIM_scheduler_Config(); - initDone = 1; } From e2e0a42d6ecd958baa49600ede67b8d4f837c73e Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Mon, 14 Mar 2022 15:07:50 +0100 Subject: [PATCH 08/12] fix: call effective ETH scheduler only from Timer callback Restrict effective ETH scheduler to Timer callback only. This is to avoid any race condition on ETH scheduler, which could previously be called from timer ISR, as well as DHCP or UDP driver parts. Any direct request for ETH scheduler (direct call to stm32_eth_scheduler()) will generate a Timer Update Event to force a call to timer callback Fixes #45 Signed-off-by: Alexandre Bourdiol --- src/utility/stm32_eth.cpp | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/utility/stm32_eth.cpp b/src/utility/stm32_eth.cpp index 73c49a0..937a297 100644 --- a/src/utility/stm32_eth.cpp +++ b/src/utility/stm32_eth.cpp @@ -95,6 +95,8 @@ static uint32_t gEhtLinkTickStart = 0; #if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100) /* Handler for stimer */ static stimer_t TimHandle; +#else + HardwareTimer *EthTim = NULL; #endif /*************************** Function prototype *******************************/ @@ -103,6 +105,9 @@ static err_t tcp_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, static err_t tcp_sent_callback(void *arg, struct tcp_pcb *tpcb, u16_t len); static void tcp_err_callback(void *arg, err_t err); static void TIM_scheduler_Config(void); +#if defined(STM32_CORE_VERSION) && (STM32_CORE_VERSION > 0x01060100) + void _stm32_eth_scheduler(void); +#endif /** * @brief Configurates the network interface @@ -148,7 +153,7 @@ static void Netif_Config(void) #if (STM32_CORE_VERSION <= 0x01080000) UNUSED(htim); #endif - stm32_eth_scheduler(); + _stm32_eth_scheduler(); } #if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100) @@ -176,7 +181,7 @@ static void TIM_scheduler_Config(void) static void TIM_scheduler_Config(void) { /* Configure HardwareTimer */ - HardwareTimer *EthTim = new HardwareTimer(DEFAULT_ETHERNET_TIMER); + EthTim = new HardwareTimer(DEFAULT_ETHERNET_TIMER); EthTim->setMode(1, TIMER_OUTPUT_COMPARE); /* Timer set to 1ms */ @@ -265,12 +270,33 @@ uint8_t stm32_eth_link_up(void) return netif_is_link_up(&gnetif); } +#if defined(STM32_CORE_VERSION) && (STM32_CORE_VERSION > 0x01060100) +/** + * @brief This function generates Timer Update event to force call to _stm32_eth_scheduler(). + * @param None + * @retval None + */ +void stm32_eth_scheduler(void) +{ + if (EthTim != NULL) { + EthTim->refresh(); + } +} + /** - * @brief This function must be called in main loop in standalone mode. + * @brief This function is called solely by Timer callback to avoid race condition. + * @param None + * @retval None + */ +void _stm32_eth_scheduler(void) +#else +/** + * @brief This function is called solely by Timer callback to avoid race condition. * @param None * @retval None */ void stm32_eth_scheduler(void) +#endif { /* Read a received packet from the Ethernet buffers and send it to the lwIP for handling */ From fb56c5415898bfa7d1cbcaee3670b7a048309c3c Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Wed, 13 Apr 2022 10:20:40 +0200 Subject: [PATCH 09/12] Fix : Wrong _tcp_client[] array initialization Former "_tcp_client[MAX_CLIENT] = {};" tries to initialize the array element with index MAX_CLIENT, which is out of array range [0 .. (MAX_CLIENT-1)] Fixes warning: warning: array subscript 32 is above array bounds of 'tcp_struct* [32]' [-Warray-bounds] Instead initialize each element of the array one by one. Signed-off-by: Alexandre Bourdiol --- src/EthernetServer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/EthernetServer.cpp b/src/EthernetServer.cpp index e006b83..5f59785 100644 --- a/src/EthernetServer.cpp +++ b/src/EthernetServer.cpp @@ -9,7 +9,9 @@ extern "C" { EthernetServer::EthernetServer(uint16_t port) { _port = port; - _tcp_client[MAX_CLIENT] = {}; + for (int i = 0; i < MAX_CLIENT; i++) { + _tcp_client[i] = {}; + } _tcp_server = {}; } From 89e4523991ee8dd9235f9a370c702a0df45911df Mon Sep 17 00:00:00 2001 From: patricklaf Date: Mon, 25 Apr 2022 16:58:03 +0200 Subject: [PATCH 10/12] feat: Add function to define port of EthernetServer at runtime --- src/EthernetServer.cpp | 6 ++++++ src/EthernetServer.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/EthernetServer.cpp b/src/EthernetServer.cpp index 5f59785..386ae9d 100644 --- a/src/EthernetServer.cpp +++ b/src/EthernetServer.cpp @@ -40,6 +40,12 @@ void EthernetServer::begin() tcp_accept(_tcp_server.pcb, tcp_accept_callback); } +void EthernetServer::begin(uint16_t port) +{ + _port = port; + begin(); +} + void EthernetServer::accept() { /* Free client if disconnected */ diff --git a/src/EthernetServer.h b/src/EthernetServer.h index 60fac5b..3a218d4 100644 --- a/src/EthernetServer.h +++ b/src/EthernetServer.h @@ -17,6 +17,7 @@ class EthernetServer : EthernetServer(uint16_t port = 80); EthernetClient available(); virtual void begin(); + virtual void begin(uint16_t port); virtual size_t write(uint8_t); virtual size_t write(const uint8_t *buf, size_t size); using Print::write; From 3d930a62337a72fef44f5ecaa6feb79451d39b88 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 26 Apr 2022 10:15:47 +0200 Subject: [PATCH 11/12] chore: bump version --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index d6b7529..f4f202c 100755 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/stm32duino/STM32Ethernet" }, - "version": "1.2.0", + "version": "1.3.0", "frameworks": "arduino", "platforms": "ststm32", "build": { From cc1e72d64fe0aaa8b3b9a9e18c093b25af6daaae Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 26 Apr 2022 10:16:23 +0200 Subject: [PATCH 12/12] chore: bump version --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index da4cf0a..3a4aaee 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino STM32Ethernet -version=1.2.0 +version=1.3.0 author=Various maintainer=STMicroelectronics sentence=Enables network connection (local and Internet) using the STM32 Board.