New lwIP-based Ethernet library for Teensy 4.1

Just checking because I used your ieee 1588-2 branch for my AES67 4.1 implementation. I did modify it to include QoS capabilities. QNEthernet is awesome thanks so much for all your work.
Are your QoS capabilities in a public fork?
 
I just released v0.34.0. Here's the Changelog:
Markdown (GitHub flavored):
## [0.34.0]

### Added
* Added tests for some of the print utility functions and classes.
* Added the `QNETHERNET_ENABLE_PING_REPLY` macro to disable ICMP echo replies.
* Added a "Requirements" section listing some library requirements to
  the README.
* Added a `QNETHERNET_PROVIDE_GNU_VERBOSE_TERMINATE_HANDLER` configuration
  option for including our own version of
  `__gnu_cxx::__verbose_terminate_handler` for space-saving reasons.
* New `StreamDecorator` class that also does `printf` checking.
* Added `driver_restart_auto_negotiation()` driver function for restarting link
  auto-negotiation. This is useful for when EMF brings the link down. A new
  "EMF interference mitigation" section was also added to the Readme.
* Added `qindesign::network::util::isBroadcast(ip, localIP, mask)`.
* New `EthernetUDP::destIP()` for getting the destination IP address from
  a received packet.

### Changed
* Improved code style and structure.
* Made `NullPrint::availableForWrite()` return `INT_MAX` instead of zero.
* Changed `EthernetUDP::stop()` to not clear the current packet.
* Changed `DNSClient::hostByName()` functions to use a default value of
  `QNETHERNET_DEFAULT_DNS_LOOKUP_TIMEOUT` for the timeout parameter.
* Improved _SimplePing_ example to catch DNS lookup errors.
* Changed ping send enable macro to `QNETHERNET_ENABLE_PING_SEND`
  from `QNETHERNET_ENABLE_PING`.
* Updated to support C++11 and C11 compilers.
* Improved setting of `errno`.
* Added `printf` checking to `PrintDecorator`.
* Replaced function-like-macros with `static inline` C functions.
* Renamed `QNETHERNET_ENABLE_ALTCP_DEFAULT_FUNCTIONS` macro
  to `QNETHERNET_PROVIDE_ALTCP_DEFAULT_FUNCTIONS`.
* `EthernetUDP` and `EthernetFrame` now share some common circular buffer code
  in an internal utility class.
* Replaced macros in `EthernetClient` with inline functions.

### Fixed
* Fixed `EthernetUDP` internal packet clear to reset all variables.
* Now keeping any manually-set link UP state sticky so that the driver can
  choose not to set it to DOWN.
* Updated _Ping_ and _SimplePing_ examples to work with other systems by
  changing use of `elapsedMillis` to `unsigned long` plus calculations.
* Fixed `ConnectionManager::iterateConnections()` calls to not call
  `Ethernet.loop()` in the callback because that could potentially invalidate
  the iterator. Also added notes about potential iteration invalidation to the
  `iterateConnections()` and `iterateListeners()` docs.
* Fixed `EthernetClient` `read()` and `peek()` to return the correct value if
  not connected.

Highlights:
* Ability to disable ping replies
* Ability to restart auto-negotiation on the Teensy 4.1
* `isBroadcast(ip, localIP, mask)` utility function for testing IPv4 addresses
* Access to the destination IP for UDP packets
* C++11 and C11 compatibility

Link: https://github.com/ssilverman/QNEthernet/releases/tag/v0.34.0
 
Working fine for me still although I haven't added any of your new stuff yet. Oh come to think of it, Aduino 2.3.7 with Paul's beta6 didn't notify me to update, I saw email of this thread.
 
Working fine for me still although I haven't added any of your new stuff yet. Oh come to think of it, Aduino 2.3.7 with Paul's beta6 didn't notify me to update, I saw email of this thread.
The updates through the Arduino IDE don’t usually propagate for a day or so.
 
I just released v0.35.0. Here's the Changelog:
Markdown (GitHub flavored):
## [0.35.0]

### Added
* Added a ping call to the main program.
* Added `qindesign::network::util::steady_clock_ms` and
  `qindesign::network::util::arm_high_resolution_clock` classes that conform to
  the _Clock_ C++ named requirement. These can be used with the `std::chrono`
  API. The first provides a wrapper for `qnethernet_hal_millis()`. The second
  wraps the ARM DWT_CYCCNT cycle counter.
* Added printing chrono clock times to network-up in the main program.
* Added `qindesign::network::util::elapsedTime<Clock>`, a class similar to
  `elapsedMillis`, but uses a `std::chrono` Clock.
* Added support to the W5500 driver for interrupts via a pin.
* New _SimpleIPerfServer_ example. It just reads from a socket as fast
  as possible.
* Added `write(const void*, size_t)` convenience functions to all
  `Print`-like classes.
* New _ChronoClocks_ example that demonstrates how to use the new Clocks and
  `std::chrono` features.
* Added `EthernetClass::linkInfo()` to replace `linkSpeed()`,
  `linkIsFullDuplex()`, and `linkIsCrossover()`.
* Implemented setting link speed, duplex, and auto-negotiation in Teensy 4.1 and
  W5500 drivers.
* Added `driver_reset_phy()` driver function for resetting the PHY.
* Added to `DriverCapabilities`:
  * `isAutoNegotiationSettable`
  * `isPHYResettable`
* Added call to `qnethernet_hal_deinit_entropy()` in `RandomDevice` destructor.
* Added `RandomDevice::entropy()` to match `std::random_device::entropy()`.
* Added `qindesign::security::random_device` to mimic `std::random_device`.
* New _ElapsedTime_ example that shows how to use the new `elapsedTime` utility.

### Changed
* Improved _Ping_ example by always sending, even if a send fails. It was
  stopping on error.
* Changed some sizes to `size_t` instead of `int`:
  * `writeFully(client, data, len)` example in the Readme
  * `EthernetClass::kMACAddrSize`
  * `EthernetClass::maxMulticastGroups()`
  * `EthernetClass::dnsServerIP(index)`
  * `EthernetClass::setDNSServerIP(index, ip)`
  * `DNSClient::maxServers()`
  * `DNSClient::setServer(index, ip)`
  * `DNSClient::getServer(index)`
  * `EthernetClient::maxSockets()`
  * `EthernetFrame::maxFrameLen()`
  * `EthernetFrame::minFrameLen()`
  * `EthernetServer::maxListeners()`
  * `EthernetUDP::maxSockets()`
  * `MDNSClass::maxServices()`
* Changed `EthernetClass::begin(mac, timeout)` return type to `bool` from `int`.
* Robustness changes:
  * Removed all implicit conversions
  * Handle all return values in some way
  * Reduced the number of #defines in favour of constants, enums, and static
    inline functions
* Changed `MDNSClass` to use `std::string` instead of the Arduino `String`.
* Updated examples to be more consistent with each other.
* Changed drivers to always loop until a frame can be sent instead of returning
  `ERR_WOULDBLOCK` or NULL.
* Marked _IPerfServer_ example as "Under Repair".
* Now excluding the FCS (Frame Check Sequence) from all frame length-related
  definitions and use.
* Made dramatic improvements to the W5500 driver with much better buffering and
  how it waits to send frames.
* Updated the W5500 driver's `driver_deinit()` function to power down the PHY.
* Updated drivers to change link settings and get link info as a group. See the
  new `LinkSettings` and `LinkInfo` structs.
* Changed all definitions of, uses of, and references to max. and min. frame
  length to exclude the FCS (frame check sequence).
* Made `QNETHERNET_ENABLE_PING_SEND` on by default.
* Updated _SNTPClient_ example to use `settimeofday()` to set the time.
* Updated _RandomNumbers_ example to use new
  `qindesign::security::random_device` class.

### Removed
* Removed from `EthernetClass` (and replaced with `linkInfo()`):
  * `linkSpeed()`
  * `linkIsFullDuplex()`
  * `linkIsCrossover()`

### Fixed
* Fixed `EthernetClass::ping(ip, ttl)` to return -1 if sending the ping failed.
* Fixed _RawFrameMonitor_ example tag interpretation to split at <=1500 and
  assume values in the range 1501-1535 are a type.
* Fixed setting an incorrect register in the entropy module (Teensy 4).
* Changed `DNSClient` to not ignore a zero timeout. This had caused a potential
  use-after-scope.
* Added better checks in the driver output for any buffer copy errors.
* Now checking for NULL buffer arguments in `write()` of `EthernetUDP`
  and `EthernetFrameClass`.
* Fixed `MDNSClass`:
  * Ensure there's final NULs after copying some strings.
  * Avoid undefined casting between `void*` and a function pointer.
  * Added some NULL argument checking.
* `DNSClient` no longer ignores a timeout of zero. This was causing a potential
  use-after-scope.
* Fixed the entropy module (Teensy 4) to not depend on a possibly stale `errno`.
* Clarified in the `EthernetServer` and `EthernetUDP` docs that the `beginXXX()`
  functions are non-transactional in that they call `end()` or `stop()` first.
* Fixed connection and listener iteration to first take a snapshot of the lists
  so that it's not possible to change the lists while iterating over them.

Highlights:
* std::chrono-compatible Clocks
* New elapsedTime<Clock> utility
* New examples:
* SimpleIPerfServer that just reads as fast as possible. IPerfServer is currently "Under Repair".
* ChronoClocks
* ElapsedTime
that demonstrates the new elapsedTime<Clock>
* New LinkSettings and LinkInfo concepts that group all the link settings and information
* New qindesign::security::random_device mimics std::random_device
* Changed some int sizes to size_t sizes
* MDNS now uses std::string instead of String
* Dramatic improvements to W5500 driver
* Ping-send is now enabled by default

Link: https://github.com/ssilverman/QNEthernet/releases/tag/v0.35.0
 
Last edited:
First of all, Shawn, thank you!

Like others who have posted, I'm not new to micros but new to Ethernet and going up the (steep) learning curve.

I'm doing this for an automotive Ethernet need and have confirmed the target is four wire full duplex (assuming) 100base-T. I'm at the very beginning point of first using the NativeEthernet library examples to confirm I can get an address from a spare 2Wire switch/router I have and have just confirmed the same using the QNEthernet simple ping example to, likewise, get an IP address from the router. My next step is to try to ping that address using a laptop on the router/switch.

I'm now starting to educate myself on how the Teensy "finds" the arduino.cc server so as to be able to ping it. I suspect there might be a way to simply ping the local router from the Teensy without the advanced steps of trying to locate a server on the internet through what I suspect is a DNS server request (as I said, very new to this). My needs are embedded Ethernet with no wide area connection thus DNS server and remote server access is not needed nor is my test set up connected to the internet to facilitate this.


My question is for those that have gone up this learning curve recently. Is there a way to transfer an amount of information or data between the Teensy and a laptop connected to a router without any other outside involvement as will be the case in the embedded environment I am targeting? I have a couple of network taps coming and was hoping to have a simple transfer working so as to learn WireShark from known (and only) activity.
 
Could you try summarizing what you're trying to do into a one-sentence question? What I'm hearing is "is it possible," and generally the answer is "yes," but I have a feeling you're trying to ask more, and I'm having trouble figuring out what that is.

Would you mind starting a new thread in the Technical Support section?
 
Last edited:
I just released v0.36.0. Here's the Changelog:
Markdown (GitHub flavored):
## [0.36.0]

### Added
* Added `elapsedTime::reset()` for resetting the timer back to zero.
* Added `rep` assignment operator and constructor to `elapsedTime` for assigning
  a count.
* Added `elapsedTime` operators that use a count.
* Added a `settimeofday()` implementation in the HAL for Teensy, gated on the
  new `QNETHERNET_PROVIDE_TEENSY_SETTIMEOFDAY` configuration macro.
* Added `qnethernet_hal_entropy_available()` function to the HAL.
* Added `operator(buf, size)` and `available()` to
  `qindesign::security::random_device`.
* Added some basic entropy randomness quality tests.
* Added `QNETHERNET_ENABLE_RAW_FRAME_FILTER_HOOK` option for determining whether
  to route incoming frames directly to the raw frame handling machinery.
  (Thanks to Folkert van Heusden for helping with this:
   <https://github.com/ssilverman/QNEthernet/issues/106#issuecomment-4619339870>)

### Changed
* Enabled raw frame loopback by default, but not raw frame support.
* Changed _SNTPClient_ example to assume that the `settimeofday()`
  function exists.
* Changed entropy functions to set `errno` to `EIO` instead of `EAGAIN` on
  entropy generation failure.
* Made the HAL's `qnethernet_hal_deinit_entropy()` and
  `qnethernet_hal_estimate entropy()` weak.
* Improved entropy and `qindesign::security::random_device` APIs.
* Updated cppreference.com URLs.
* Moved driver C functions into namespace `qindesign::network::driver`.
* Moved entropy C functions into namespace `qindesign::entropy`.
* Changed `QNETHERNET_FLUSH_AFTER_WRITE` to `QNETHERNET_FLUSH_AFTER_TCP_WRITE`.

### Removed
* Removed `qindesign::security::RandomDevice` in favour of the
  `std::random_device`-mimicking `qindesign::security::random_device`.

### Fixed
* Fixed the _ElapsedTime_ example to actually toggle the LED.
* Fixed Teensy 4.1 driver to clear the MAC address hash-collision bookkeeping
  when the driver is uninitialized.
* Fixed TRNG (entropy) access for lower operating frequencies, on Teensy 4.
* Fixed to add some `errno` assignments and update some related comments
  and docs.
* Fixed TRNG initialization to use the correct macros.
* Fixed raw frame loopback to pass along broadcast frames.
  (Thanks to Folkert van Heusden:
   <https://github.com/ssilverman/QNEthernet/issues/106#issuecomment-4639110163>)
* Fixed Teensy 4.1 driver to not overwrite output source MAC address.
  (Thanks to Folkert van Heusden:
   <https://github.com/ssilverman/QNEthernet/issues/106#issuecomment-4638274539>)
* Fixed Teensy 4.1 driver to not calculate checksums when sending raw frames.
  (Thanks to Folkert van Heusden:
   <https://github.com/ssilverman/QNEthernet/issues/106#issuecomment-4697867441>,
   <https://github.com/ssilverman/QNEthernet/issues/106#issuecomment-4754025776>)
* Fixed Ping to calculate the ICMP checkum if needed.

Highlights:
* Added some `elapsedTime` operators
* `settimeofday()` implementation on Teensy
* New basic entropy quality tests
* Added the ability to filter incoming raw frames and have them go directly to the raw frame API
* Moved most of the C code to C++
* Removed `qindesign::security::RandomDevice` in favour of the `std::random_device`-mimicking `qindesign::security::random_device`
* Fixed some raw frame-related problems (thanks to Folkert van Heusden for the assistance and reports)
* Fixed ping to calculate the outgoing ICMP checksum when appropriate

Link: https://github.com/ssilverman/QNEthernet/releases/tag/v0.36.0
 
@shawn - One little issue with QNEthernet v0.36.0. The example "RawFrameMonitor.ino" fails to compile with this error:
Code:
RawFrameMonitor: In function 'void loop()':
RawFrameMonitor:119: error: 'EthernetFrame' was not declared in this scope
  119 |   int size = EthernetFrame.parseFrame();
      |              ^~~~~~~~~~~~~
Using library QNEthernet-master at version 0.37.0-snapshot in folder: /home/wwatson/Arduino/libraries/QNEthernet-master
The sketch does not seem to recognize EthernetFrameClass so:
Code:
  int size = EthernetFrame.parseFrame();
Fails...

EDIT: Scratch this post. I changed "QNETHERNET_ENABLE_RAW_FRAME_SUPPORT" to 1 in "qnethernet_opts.h" but evidently did not save the file afterwards. The sketch compiles and runs ok...
 
Last edited:
@wwatson that's because support for raw frames is disabled by default. You can enable it by either adding the QNETHERNET_ENABLE_RAW_FRAME_SUPPORT=1 macro to the compiler options or by setting it to 1 in qnethernet_opts.h.

There are some good reasons right now why I'm doing it this way. One is code size, and the other is that if raw frames are enabled, then a few MAC accelerator functions are disabled for the Teensy 4.1 driver. Now, I know not all drivers necessarily care — some might — but I need to look at a few more things. I'm hesitant to enable features by default that I don't think most people use.

See also the notes at the top of the RawFrameMonitor example. (There's a mistake where it says the default is 'enabled'.)
 
Last edited:
@wwatson that's because support for raw frames is disabled by default. You can enable it by either adding the QNETHERNET_ENABLE_RAW_FRAME_SUPPORT=1 macro to the compiler options or by setting it to 1 in qnethernet_opts.h.

There are some good reasons right now why I'm doing it this way. One is code size, and the other is that if raw frames are enabled, then a few MAC accelerator functions are disabled for the Teensy 4.1 driver. Now, I know not all drivers necessarily care — some might — but I need to look at a few more things. I'm hesitant to enable features by default that I don't think most people use.

See also the notes at the top of the RawFrameMonitor example. (There's a mistake where it says the default is 'enabled'.)
Sorry, It was my fault I did not save the change. It's working ok now after saving "qnethernet_opts.h" :rolleyes:
QNEthernet v0.36.0 is now working with the WIFI board with some good news. I'll post it in the other thread...
 
Back
Top