Skip to content

Commit

Permalink
STM32 Ethernet support
Browse files Browse the repository at this point in the history
  • Loading branch information
pmantoine committed Sep 28, 2024
1 parent dc481a2 commit 07ab728
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 79 deletions.
128 changes: 77 additions & 51 deletions EthernetInterface.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/*
* © 2024 Morten "Doc" Nielsen
* © 2023-2024 Paul M. Antoine
* © 2022 Bruno Sanches
* © 2021 Fred Decker
* © 2020-2022 Harald Barth
* © 2020-2021 Chris Harlow
* © 2020-2024 Chris Harlow
* © 2020 Gregor Baues
* All rights reserved.
*
Expand Down Expand Up @@ -36,9 +38,14 @@
MDNS mdns(udp);
#endif


//extern void looptimer(unsigned long timeout, const FSH* message);
#define looptimer(a,b)

bool EthernetInterface::connected=false;
EthernetServer * EthernetInterface::server= nullptr;
EthernetClient EthernetInterface::clients[MAX_SOCK_NUM]; // accept up to MAX_SOCK_NUM client connections at the same time; This depends on the chipset used on the Shield
bool EthernetInterface::inUse[MAX_SOCK_NUM]; // accept up to MAX_SOCK_NUM client connections at the same time; This depends on the chipset used on the Shield
uint8_t EthernetInterface::buffer[MAX_ETH_BUFFER+1]; // buffer used by TCP for the recv
RingStream * EthernetInterface::outboundRing = nullptr;

Expand All @@ -47,12 +54,13 @@ RingStream * EthernetInterface::outboundRing = nullptr;
*
*/

void EthernetInterface::setup() // STM32 VERSION
void EthernetInterface::setup()
{
DIAG(F("Ethernet begin"
DIAG(F("Ethernet starting"
#ifdef DO_MDNS
" with mDNS"
" (with mDNS)"
#endif
" Please be patient, especially if no cable is connected!"
));

#ifdef STM32_ETHERNET
Expand Down Expand Up @@ -116,6 +124,47 @@ void EthernetInterface::setup() // STM32 VERSION
connected=true;
}

#if defined (STM32_ETHERNET)
void EthernetInterface::acceptClient() { // STM32 version
auto client=server->available();
if (!client) return;
// check for existing client
for (byte socket = 0; socket < MAX_SOCK_NUM; socket++)
if (inUse[socket] && client == clients[socket]) return;

// new client
for (byte socket = 0; socket < MAX_SOCK_NUM; socket++)
{
if (!inUse[socket])
{
clients[socket] = client;
inUse[socket]=true;
if (Diag::ETHERNET)
DIAG(F("Ethernet: New client socket %d"), socket);
return;
}
}
DIAG(F("Ethernet OVERFLOW"));
}
#else
void EthernetInterface::acceptClient() { // non-STM32 version
auto client=server->accept();
if (!client) return;
auto socket=client.getSocketNumber();
clients[socket]=client;
inUse[socket]=true;
if (Diag::ETHERNET)
DIAG(F("Ethernet: New client socket %d"), socket);
}
#endif

void EthernetInterface::dropClient(byte socket)
{
clients[socket].stop();
inUse[socket]=false;
CommandDistributor::forget(socket);
if (Diag::ETHERNET) DIAG(F("Ethernet: Disconnect %d "), socket);
}

/**
* @brief Main loop for the EthernetInterface
Expand All @@ -124,15 +173,17 @@ void EthernetInterface::setup() // STM32 VERSION
void EthernetInterface::loop()
{
if (!connected) return;

looptimer(5000, F("E.loop"));

static bool warnedAboutLink=false;
if (Ethernet.linkStatus() == LinkOFF){
if (warnedAboutLink) return;
DIAG(F("Ethernet link OFF"));
warnedAboutLink=true;
return;
}

looptimer(5000, F("E.loop warn"));

// link status must be ok here
if (warnedAboutLink) {
DIAG(F("Ethernet link RESTORED"));
Expand All @@ -142,6 +193,8 @@ void EthernetInterface::loop()
#ifdef DO_MDNS
// Always do this because we don't want traffic to intefere with being found!
mdns.run();
looptimer(5000, F("E.mdns"));

#endif

//
Expand All @@ -161,50 +214,22 @@ void EthernetInterface::loop()
//DIAG(F("maintained"));
break;
}
looptimer(5000, F("E.maintain"));

// get client from the server
acceptClient();

// get client from the server
#if defined (STM32_ETHERNET)
// STM32Ethernet doesn't use accept(), just available()
auto client = server->available();
if (client) {
// check for new client
byte socket;
bool sockfound = false;
for (socket = 0; socket < MAX_SOCK_NUM; socket++)
{
if (client == clients[socket])
{
sockfound = true;
break;
}
}
if (!sockfound)
{ // new client
for (socket = 0; socket < MAX_SOCK_NUM; socket++)
{
if (!clients[socket])
{
clients[socket] = client;
sockfound=true;
if (Diag::ETHERNET)
DIAG(F("Ethernet: New client socket %d"), socket);
break;
}
}
}
if (!sockfound) DIAG(F("new Ethernet OVERFLOW"));
}

#else
auto client = server->accept();
if (client) clients[client.getSocketNumber()]=client;
#endif

// handle disconnected sockets because STM32 library doesnt
// do the read==0 response.
for (byte socket = 0; socket < MAX_SOCK_NUM; socket++)
{
if (inUse[socket] && !clients[socket].connected()) dropClient(socket);
}

// check for incoming data from all possible clients
for (byte socket = 0; socket < MAX_SOCK_NUM; socket++)
{
if (!clients[socket]) continue; // socket is not in use
if (!inUse[socket]) continue; // socket is not in use

// read any bytes from this client
auto count = clients[socket].read(buffer, MAX_ETH_BUFFER);
Expand All @@ -216,14 +241,13 @@ void EthernetInterface::loop()
if (Diag::ETHERNET) DIAG(F("Ethernet s=%d, c=%d b=:%e"), socket, count, buffer);
// execute with data going directly back
CommandDistributor::parse(socket,buffer,outboundRing);
//looptimer(5000, F("Ethloop2 parse"));
return; // limit the amount of processing that takes place within 1 loop() cycle.
}

// count=0 The client has disconnected
clients[socket].stop();
CommandDistributor::forget(socket);
if (Diag::ETHERNET) DIAG(F("Ethernet: disconnect %d "), socket);
}
dropClient(socket);
}

WiThrottle::loop(outboundRing);

Expand All @@ -245,9 +269,11 @@ void EthernetInterface::loop()
tmpbuf[i] = outboundRing->read();
}
tmpbuf[count]=0;
if (Diag::ETHERNET) DIAG(F("Ethernet reply s=%d, c=%d, b:%e"),
if (inUse[socketOut]) {
if (Diag::ETHERNET) DIAG(F("Ethernet reply s=%d, c=%d, b:%e"),
socketOut,count,tmpbuf);
clients[socketOut].write(tmpbuf,count);
clients[socketOut].write(tmpbuf,count);
}
}

}
Expand Down
9 changes: 8 additions & 1 deletion EthernetInterface.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/*
* © 2023-2024 Paul M. Antoine
* © 2021 Neil McKechnie
* © 2021 Mike S
* © 2021 Fred Decker
* © 2020-2021 Chris Harlow
* © 2020-2022 Harald Barth
* © 2020-2024 Chris Harlow
* © 2020 Gregor Baues
* All rights reserved.
*
Expand Down Expand Up @@ -35,6 +37,7 @@
#if defined (ARDUINO_TEENSY41)
#include <NativeEthernet.h> //TEENSY Ethernet Treiber
#include <NativeEthernetUdp.h>
#define MAX_SOCK_NUM 4
#elif defined (ARDUINO_NUCLEO_F429ZI) || defined (ARDUINO_NUCLEO_F439ZI) || defined (ARDUINO_NUCLEO_F4X9ZI)
#include <LwIP.h>
// #include "STM32lwipopts.h"
Expand Down Expand Up @@ -67,8 +70,12 @@ class EthernetInterface {
static bool connected;
static EthernetServer * server;
static EthernetClient clients[MAX_SOCK_NUM]; // accept up to MAX_SOCK_NUM client connections at the same time; This depends on the chipset used on the Shield
static bool inUse[MAX_SOCK_NUM]; // accept up to MAX_SOCK_NUM client connections at the same time; This depends on the chipset used on the Shield
static uint8_t buffer[MAX_ETH_BUFFER+1]; // buffer used by TCP for the recv
static RingStream * outboundRing;
static void acceptClient();
static void dropClient(byte socketnum);

};

#endif
5 changes: 3 additions & 2 deletions I2CManager_STM32.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@
*****************************************************************************/
#if defined(I2C_USE_INTERRUPTS) && defined(ARDUINO_ARCH_STM32)
#if defined(ARDUINO_NUCLEO_F401RE) || defined(ARDUINO_NUCLEO_F411RE) || defined(ARDUINO_NUCLEO_F446RE) \
|| defined(ARDUINO_NUCLEO_F412ZG) || defined(ARDUINO_NUCLEO_F413ZH) \
|| defined(ARDUINO_NUCLEO_F429ZI) || defined(ARDUINO_NUCLEO_F446ZE)
|| defined(ARDUINO_NUCLEO_F412ZG) || defined(ARDUINO_NUCLEO_F413ZH) || defined(ARDUINO_NUCLEO_F446ZE) \
|| defined(ARDUINO_NUCLEO_F429ZI) || defined(ARDUINO_NUCLEO_F439ZI) || defined(ARDUINO_NUCLEO_F4X9ZI)

// Assume I2C1 for now - default I2C bus on Nucleo-F411RE and likely all Nucleo-64
// and Nucleo-144 variants
I2C_TypeDef *s = I2C1;
Expand Down
10 changes: 9 additions & 1 deletion MotorDrivers.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,19 @@
#define SAMD_STANDARD_MOTOR_SHIELD STANDARD_MOTOR_SHIELD
#define STM32_STANDARD_MOTOR_SHIELD STANDARD_MOTOR_SHIELD

#if defined(ARDUINO_NUCLEO_F429ZI) || defined(ARDUINO_NUCLEO_F439ZI) || defined(ARDUINO_NUCLEO_F4X9ZI)
// EX 8874 based shield connected to a 3V3 system with 12-bit (4096) ADC
// The Ethernet capable STM32 models cannot use Channel B BRAKE on D8, and must use the ALT pin of D6,
// AND cannot use Channel B PWN on D11, but must use the ALT pin of D5
#define EX8874_SHIELD F("EX8874"), \
new MotorDriver( 3, 12, UNUSED_PIN, 9, A0, 1.27, 5000, A4), \
new MotorDriver( 5, 13, UNUSED_PIN, 6, A1, 1.27, 5000, A5)
#else
// EX 8874 based shield connected to a 3V3 system with 12-bit (4096) ADC
#define EX8874_SHIELD F("EX8874"), \
new MotorDriver( 3, 12, UNUSED_PIN, 9, A0, 1.27, 5000, A4), \
new MotorDriver(11, 13, UNUSED_PIN, 8, A1, 1.27, 5000, A5)

#endif

#elif defined(ARDUINO_ARCH_ESP32)
// STANDARD shield on an ESPDUINO-32 (ESP32 in Uno form factor). The shield must be eiter the
Expand Down
55 changes: 33 additions & 22 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ monitor_speed = 115200
monitor_echo = yes

[env:Nucleo-F411RE]
platform = ststm32
platform = ststm32 @ 17.6.0
board = nucleo_f411re
framework = arduino
lib_deps = ${env.lib_deps}
Expand All @@ -211,7 +211,7 @@ monitor_speed = 115200
monitor_echo = yes

[env:Nucleo-F446RE]
platform = ststm32
platform = ststm32 @ 17.6.0
board = nucleo_f446re
framework = arduino
lib_deps = ${env.lib_deps}
Expand All @@ -223,7 +223,7 @@ monitor_echo = yes
; tested as yet
;
[env:Nucleo-F401RE]
platform = ststm32
platform = ststm32 @ 17.6.0
board = nucleo_f401re
framework = arduino
lib_deps = ${env.lib_deps}
Expand All @@ -236,7 +236,7 @@ monitor_echo = yes
; installed before you can let PlatformIO see this
;
; [env:Nucleo-F413ZH]
; platform = ststm32
; platform = ststm32 @ 17.6.0
; board = nucleo_f413zh
; framework = arduino
; lib_deps = ${env.lib_deps}
Expand All @@ -248,7 +248,7 @@ monitor_echo = yes
; installed before you can let PlatformIO see this
;
[env:Nucleo-F446ZE]
platform = ststm32
platform = ststm32 @ 17.6.0
board = nucleo_f446ze
framework = arduino
lib_deps = ${env.lib_deps}
Expand All @@ -260,8 +260,8 @@ monitor_echo = yes
; installed before you can let PlatformIO see this
;
; [env:Nucleo-F412ZG]
; platform = ststm32
; board = blah_f412zg
; platform = ststm32 @ 17.6.0
; board = nucleo_f412zg
; framework = arduino
; lib_deps = ${env.lib_deps}
; build_flags = -std=c++17 -Os -g2 -Wunused-variable
Expand All @@ -272,12 +272,12 @@ monitor_echo = yes
; Experimental - Ethernet work still in progress
;
[env:Nucleo-F429ZI]
platform = ststm32
platform = ststm32 @ 17.6.0
board = nucleo_f429zi
framework = arduino
lib_deps = ${env.lib_deps}
stm32duino/STM32Ethernet @ ^1.3.0
stm32duino/STM32duino LwIP @ ^2.1.2
stm32duino/STM32Ethernet @ ^1.4.0
stm32duino/STM32duino LwIP @ ^2.1.3
MDNS_Generic
lib_ignore = WiFi101
WiFi101_Generic
Expand All @@ -289,18 +289,29 @@ monitor_speed = 115200
monitor_echo = yes
upload_protocol = stlink

; [env:Nucleo-F429ZI]
; platform = ststm32
; board = nucleo_f429zi
; framework = arduino
; lib_deps = ${env.lib_deps}
; arduino-libraries/Ethernet @ ^2.0.1
; stm32duino/STM32Ethernet @ ^1.3.0
; stm32duino/STM32duino LwIP @ ^2.1.2
; build_flags = -std=c++17 -Os -g2 -Wunused-variable
; monitor_speed = 115200
; monitor_echo = yes
; upload_protocol = stlink
; Experimental - Ethernet work still in progress
;
[env:Nucleo-F439ZI]
platform = ststm32 @ 17.6.0
; board = nucleo_f439zi
; Temporarily treat it as an F429ZI (they are code compatible) until
; the PR to PlatformIO to update the F439ZI JSON file is available
; PMA - 28-Sep-2024
board = nucleo_f429zi
framework = arduino
lib_deps = ${env.lib_deps}
stm32duino/STM32Ethernet @ ^1.4.0
stm32duino/STM32duino LwIP @ ^2.1.3
MDNS_Generic
lib_ignore = WiFi101
WiFi101_Generic
WiFiEspAT
WiFiMulti_Generic
WiFiNINA_Generic
build_flags = -std=c++17 -Os -g2 -Wunused-variable
monitor_speed = 115200
monitor_echo = yes
upload_protocol = stlink

[env:Teensy3_2]
platform = teensy
Expand Down
Loading

0 comments on commit 07ab728

Please sign in to comment.