send RAW ethernet message with Teensy 4.1 and FNET

cj84

Member
Hi,

my task is to use the ethernet interface of the Teensy 4.1. So far, so good, there is an implementation with the FNET stack and with the lwip stack.

Let's go deeper into my requirements:
  • use IPv6 and send receive UDP messages
  • implement PTPv2 communication and send/receive raw messages
  • the messages are located on the MAC-layer. Since I have written my own implementation, I only need the bytes received by the phy and need to send an array of bytes with the phy​

What I have managed so far:
  • FNET/NativeEthernet:
  • send and receive IPv6 UDP packets​
  • found and print the received bytes before processing​
  • lwip/QNEthernet:
  • send raw packages with the provided function​
  • (hopefully) identified the receive function with the RAW bytes​

Where is my problem:
  • I need to use both functions with one stack (since I guess both stacks in parallel won't work)
  • when I configure IPv6 on lwip I get a quite load of errors I was not able to solve (I tried on the first one that looked quite simple and I had no success - since FNET worked I did not spent more time on that by now)
  • I tried to send a RAW message with the FNET stack with the function void fnet_fec_output(fnet_netif_t *netif, fnet_netbuf_t *nb). The controller locked up. I guess there are some dependencies on DMA memory or socket allocations that are needed.

What I would like to have:
  • An example how to create with FNET a raw socket or send a raw message without any additional information/headers
  • A hint where to manipulate the receive functions to receive the message I want to process (a PTPv2 message has a unique MAC destination address I will have to listen on) in FNET

Thank you for reading and have a nice day
 
Is your goal to just send and receive IPv6 packets or is it IPv6 plus send and receive raw packets? (All with PTP.)
 
Is your goal to just send and receive IPv6 packets or is it IPv6 plus send and receive raw packets? (All with PTP.)

It is my goal to send IPv6 packets and additionally to send RAW packets.

The IPv6 UDP messages are used for other data (related to the PTP timestamp but not for the PTP service itself). I want to use the RAW packets for the PTPv2 protocol, since it is located outside of the IP-layer. https://wiki.wireshark.org/Protocols/ptp -> "Starting with IEEE1588 Version2, a native Layer2 Ethernet implementation was designed. PTP can use Ethernet as its transport protocol. The well known Ethernet type for PTP traffic is 0x88F7". I know that the PTP service can be used with UDP, but this is not what I want here. I'm sorry if this was confusing.

In the FNET stack IPv6 is preactivated and I managed to create INET6 sockets for sending (and IPv6 UDP packets are received by the existent functions).

Unfortunately I did not understand how to send a pure (RAW) byte array without all the protocols (this was easily possible with QNEthernet but there I lack of IPv6 support yet)

SOCK_RAW in FNET was an option, but except of the ping service there are no further examples or usages (and the ping service will also use IPv4 or IPv6).
The function void fnet_fec_output(fnet_netif_t *netif, fnet_netbuf_t *nb) seems to be the lowest level of send function and place data in the DMA chain of the phy but since there are a lot of pointer constructs and I'm not able to debug right now with the Teensy 4.1 it is hard to find the right parameters or follow the call instances. So I was hoping that someone might have a deeper understanding of the FNET stack.
 
Thanks for the extra detail. I want to add raw packet reception to the QNEthernet API next, and I think I’ll try to add IPv6 after that. I don’t have a timeline for this, however. It’s a “when I have time” thing.
 
Thank you very much for the adoption of the feature request.

If I may help you with code or testing don't hesitate to ask. In one or two months this project will ramp up again and I will have this "time thing" for a couple of weeks. And a student supports the IPv6 task at the moment. He may work full time with this topic if he gets some assistance.
 
I just released v0.12.0 with a new raw Ethernet frame API, `EthernetFrame`. You can now send and receive frames that lwIP doesn't know about. See the release notes.
 
If you must use FNET it is a little bit more complicated to use the low level functions, but it is possible with a little bit of work. I've done it so I can walk you through it if need be, you can send raw frames without having to modify the library, but to receive raw frames you have to add the ethertype and a receive function to the fnet_eth_prot_if_list array.
 
Hi vjmuzik,

thank you for the offer to help with sending raw messages together with the FNET stack.

For the moment I have no favorite stack. Since I had a lot of effort to get IPv6 UDP working I thought to add a raw message would be easier than to get IPv6 working with the lwip stack (that has easy raw messages together with the QNEthernet API thanks to shawn).

So, I do not have to use the FNET stack, but I really would like to try it with that. If you are interested, I may share my IPv6 experiments and we can "officially" expand the NativeEthernet lib with IPv6 UDP functions and an examaple (since IPv6 lacks on examples and implementations on embedded devices as far as the internet searches are telling me).

My student is working on a test gui onwindows side for IP and raw communication. Once it is finished we can test the fnet stack and the lwip stack in both directions. In my opinion it would be great for the community to enable both stacks with IPv6 and raw features and examples. I will estimate that I may work fulltime on this project with the beginning of march. Then I can respond and test a bit more quicker than now (sorry for the long response times).

I tried to use the function void fnet_fec_output(fnet_netif_t netif, fnet_netbuf_t nb)

Code:
void SendRawMessage(void){
  fnet_netif_desc_t tempDefaultHw = fnet_netif_get_default();
  fnet_netif_t netif = (fnet_netif_t )tempDefaultHw;
  fnet_netbuf_t tempEthernetBuffer;

  uint8_t tempDataBuffer[60] ={
  0x01,0x8e,0xc2,0x0e,0x0e,0x0e,0x02,0x7d,0xfa,
  0x00,0x10,0x02,0x88,0xf7,0x10,0x02,0x00,0x2c,
  0x00,0x00,0x02,0x08,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x7e,
  0xfe,0xfe,0xfe,0x00,0x10,0x02,0x00,0x02,0x0a,
  0x9e,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00};
  
  tempEthernetBuffer.data = &tempDataBuffer[0];
  tempEthernetBuffer.data_ptr = tempDataBuffer;
  tempEthernetBuffer.length = 60;
  tempEthernetBuffer.total_length = 1;
  fnet_fec_output(netif, &tempEthernetBuffer);
}

But the controller hangs after that.

I was expecting some DMA buffers that are used by the ethernet interface (I had not the time to read the data sheet for that part for now) and experimented with some socket allocations since I have seen that they allocate buffers with DMA pragmas. But I have not yet tested it:

Code:
bool EthernetClass::socketSendRaw(uint8_t s, fnet_flag_t flags)
{
    fnet_socket_if_t    *sock;
    sock = *(fnet_socket_if_t **)s;
    fnet_netbuf_t               *nb;
    nb = _fnet_netbuf_from_buf(socket_buf_transmit[s], socket_buf_len[s], FNET_FALSE);
    fnet_netif_t    *netif_default = _fnet_netif_get_default();
     
    fnet_fec_output(netif_default,nb);

    return true;
}
 
I implemented IPv6 in QNEthernet but it needs some more testing if you’re willing to do that.
 
Well you are my hero!
I'm lacking on Ethernet hardware right now since I gave my board to a colleague for testing the software on a rack. But I will try to compile the new implementation and try to follow the calls. Is it integrated in the library manager or should I download it from the repo?

The test of the raw message implementation is still in progress. I'm sorry for the delays in responding. We are still working on the Windows-Side to have a test possibility of the different message types (UDP IPv4, UDP IPv6 and raw messages).
 
I implemented IPv6 in QNEthernet but it needs some more testing if you’re willing to do that.

Hi,

I generated a test project and integrated via platform.io library manager <QNEthernet> 0.14.0-snapshot.

Code:
[env:teensy41]
platform = teensy
board = teensy41
framework = arduino
lib_deps = ssilverman/QNEthernet@^0.14.0-snapshot

I got the following warning during installation:
Library Manager: Installing ssilverman/QNEthernet @ ^0.14.0-snapshot
Warning! Could not find the package with 'ssilverman/QNEthernet @ ^0.14.0-snapshot' requirements for your system 'windows_amd64'

Since I do not use 'windows_amd64' I think this could be ignored

Then I try to activate LWIP IPv6 in opt.h

Code:
/*
   ---------------------------------------
   ---------- IPv6 options ---------------
   ---------------------------------------
*/
/**
 * @defgroup lwip_opts_ipv6 IPv6
 * @ingroup lwip_opts
 * @{
 */
/**
 * LWIP_IPV6==1: Enable IPv6
 */
#if !defined LWIP_IPV6 || defined __DOXYGEN__
#define LWIP_IPV6                       1
#endif

When I start compilation I will get multiple errors


Code:
Compiling .pio\build\teensy41\lib9da\QNEthernet\QNEthernetClient.cpp.o
.pio\libdeps\teensy41\QNEthernet\src\QNDNSClient.cpp: In static member function 'static void qindesign::network::DNSClient::dnsFoundFunc(const char*, const ip_addr_t*, void*)':
.pio\libdeps\teensy41\QNEthernet\src\QNDNSClient.cpp:23:25: error: 'const ip_addr_t {aka const struct ip_addr}' has no member named 'addr'
   req->callback(ipaddr->addr);
                         ^
.pio\libdeps\teensy41\QNEthernet\src\QNDNSClient.cpp: In static member function 'static IPAddress qindesign::network::DNSClient::getServer(int)':
.pio\libdeps\teensy41\QNEthernet\src\QNDNSClient.cpp:41:42: error: 'const ip_addr_t {aka const struct ip_addr}' has no member named 'addr'
   return IPAddress{dns_getserver(index)->addr};
                                          ^
.pio\libdeps\teensy41\QNEthernet\src\QNDNSClient.cpp:41:46: error: no matching function for call to 'IPAddress::IPAddress(<brace-enclosed initializer list>)'
   return IPAddress{dns_getserver(index)->addr};
                                              ^
In file included from .pio\libdeps\teensy41\QNEthernet\src\QNDNSClient.h:13:0,
                 from .pio\libdeps\teensy41\QNEthernet\src\QNDNSClient.cpp:7:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:61:2: note: candidate: IPAddress::IPAddress(const uint8_t*)
  IPAddress(const uint8_t *address) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:61:2: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:58:2: note: candidate: IPAddress::IPAddress(uint32_t)
  IPAddress(uint32_t address) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:58:2: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:52:2: note: candidate: IPAddress::IPAddress(uint8_t, uint8_t, uint8_t, uint8_t)
  IPAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:52:2: note:   candidate expects 4 arguments, 1 provided
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:49:2: note: candidate: IPAddress::IPAddress()
  IPAddress() {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:49:2: note:   candidate expects 0 arguments, 1 provided
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note: candidate: constexpr IPAddress::IPAddress(const IPAddress&)
 class IPAddress : public Printable {
       ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note: candidate: constexpr IPAddress::IPAddress(IPAddress&&)
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note:   conversion of argument 1 would be ill-formed:
.pio\libdeps\teensy41\QNEthernet\src\QNDNSClient.cpp: In static member function 'static bool qindesign::network::DNSClient::getHostByName(const char*, std::function<void(IPAddress)>)':
.pio\libdeps\teensy41\QNEthernet\src\QNDNSClient.cpp:57:21: error: 'ip_addr_t {aka struct ip_addr}' has no member named 'addr'
       callback(addr.addr);
                     ^
*** [.pio\build\teensy41\lib9da\QNEthernet\QNDNSClient.cpp.o] Error 1
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp: In member function 'bool qindesign::network::EthernetClass::begin(const IPAddress&, const IPAddress&, const IPAddress&)':
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:151:16: error: 'ip_addr_t {aka struct ip_addr}' has no member named 'addr'
     if (ipaddr.addr != IPADDR_ANY ||
                ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:152:17: error: 'ip_addr_t {aka struct ip_addr}' has no member named 'addr'
         netmask.addr != IPADDR_ANY ||
                 ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:153:12: error: 'ip_addr_t {aka struct ip_addr}' has no member named 'addr'
         gw.addr != IPADDR_ANY) {
            ^
In file included from .pio\libdeps\teensy41\QNEthernet\src/lwip/ip.h:46:0,
                 from .pio\libdeps\teensy41\QNEthernet\src/lwip/tcp.h:48,
                 from .pio\libdeps\teensy41\QNEthernet\src\internal/ConnectionState.h:14,
                 from .pio\libdeps\teensy41\QNEthernet\src\internal/ConnectionHolder.h:13,
                 from .pio\libdeps\teensy41\QNEthernet\src\QNEthernetClient.h:18,
                 from .pio\libdeps\teensy41\QNEthernet\src\QNEthernet.h:19,
                 from .pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:7:
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp: In lambda function:
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:183:56: error: cannot convert 'const ip4_addr_t* {aka const ip4_addr*}' to 'const ip_addr_t* {aka const ip_addr*}' for argument '1' to 'void enet_join_group(const ip_addr_t*)'
                                   enet_join_group(group);
                                                        ^
.pio\libdeps\teensy41\QNEthernet\src/lwip/netif.h:492:106: note: in definition of macro 'netif_set_igmp_mac_filter'
 #define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0)
                                                                                                          ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:186:57: error: cannot convert 'const ip4_addr_t* {aka const ip4_addr*}' to 'const ip_addr_t* {aka const ip_addr*}' for argument '1' to 'void enet_leave_group(const ip_addr_t*)'
                                   enet_leave_group(group);
                                                         ^
.pio\libdeps\teensy41\QNEthernet\src/lwip/netif.h:492:106: note: in definition of macro 'netif_set_igmp_mac_filter'
 #define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0)
                                                                                                          ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp: In member function 'bool qindesign::network::EthernetClass::begin(const ip_addr_t*, const ip_addr_t*, const ip_addr_t*)':
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:199:15: error: 'const ip_addr_t {aka const struct ip_addr}' has no member named 'addr'
   if (ipaddr->addr != IPADDR_ANY ||
               ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:200:16: error: 'const ip_addr_t {aka const struct ip_addr}' has no member named 'addr'
       netmask->addr != IPADDR_ANY ||
                ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:201:11: error: 'const ip_addr_t {aka const struct ip_addr}' has no member named 'addr'
       gw->addr != IPADDR_ANY) {
           ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp: In member function 'bool qindesign::network::EthernetClass::waitForLocalIP(uint32_t)':
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:218:34: error: 'const ip_addr_t {aka const struct ip_addr}' has no member named 'addr'
   while (netif_ip_addr4(netif_)->addr == 0 && timer < timeout) {
                                  ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:221:35: error: 'const ip_addr_t {aka const struct ip_addr}' has no member named 'addr'
   return (netif_ip_addr4(netif_)->addr != 0);
                                   ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp: In member function 'IPAddress qindesign::network::EthernetClass::localIP() const':
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:294:44: error: 'const ip_addr_t {aka const struct ip_addr}' has no member named 'addr'
   return IPAddress{netif_ip_addr4(netif_)->addr};
                                            ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:294:48: error: no matching function for call to 'IPAddress::IPAddress(<brace-enclosed initializer list>)'
   return IPAddress{netif_ip_addr4(netif_)->addr};
                                                ^
In file included from .pio\libdeps\teensy41\QNEthernet\src\QNEthernet.h:15:0,
                 from .pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:7:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:61:2: note: candidate: IPAddress::IPAddress(const uint8_t*)
  IPAddress(const uint8_t *address) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:61:2: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:58:2: note: candidate: IPAddress::IPAddress(uint32_t)
  IPAddress(uint32_t address) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:58:2: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:52:2: note: candidate: IPAddress::IPAddress(uint8_t, uint8_t, uint8_t, uint8_t)
  IPAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:52:2: note:   candidate expects 4 arguments, 1 provided
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:49:2: note: candidate: IPAddress::IPAddress()
  IPAddress() {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:49:2: note:   candidate expects 0 arguments, 1 provided
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note: candidate: constexpr IPAddress::IPAddress(const IPAddress&)
 class IPAddress : public Printable {
       ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note: candidate: constexpr IPAddress::IPAddress(IPAddress&&)
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note:   conversion of argument 1 would be ill-formed:
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp: In member function 'IPAddress qindesign::network::EthernetClass::subnetMask() const':
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:301:47: error: 'const ip_addr_t {aka const struct ip_addr}' has no member named 'addr'
   return IPAddress{netif_ip_netmask4(netif_)->addr};
                                               ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:301:51: error: no matching function for call to 'IPAddress::IPAddress(<brace-enclosed initializer list>)'
   return IPAddress{netif_ip_netmask4(netif_)->addr};
                                                   ^
In file included from .pio\libdeps\teensy41\QNEthernet\src\QNEthernet.h:15:0,
                 from .pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:7:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:61:2: note: candidate: IPAddress::IPAddress(const uint8_t*)
  IPAddress(const uint8_t *address) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:61:2: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:58:2: note: candidate: IPAddress::IPAddress(uint32_t)
  IPAddress(uint32_t address) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:58:2: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:52:2: note: candidate: IPAddress::IPAddress(uint8_t, uint8_t, uint8_t, uint8_t)
  IPAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:52:2: note:   candidate expects 4 arguments, 1 provided
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:49:2: note: candidate: IPAddress::IPAddress()
  IPAddress() {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:49:2: note:   candidate expects 0 arguments, 1 provided
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note: candidate: constexpr IPAddress::IPAddress(const IPAddress&)
 class IPAddress : public Printable {
       ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note: candidate: constexpr IPAddress::IPAddress(IPAddress&&)
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note:   conversion of argument 1 would be ill-formed:
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp: In member function 'IPAddress qindesign::network::EthernetClass::gatewayIP() const':
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:308:42: error: 'const ip_addr_t {aka const struct ip_addr}' has no member named 'addr'
   return IPAddress{netif_ip_gw4(netif_)->addr};
                                          ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:308:46: error: no matching function for call to 'IPAddress::IPAddress(<brace-enclosed initializer list>)'
   return IPAddress{netif_ip_gw4(netif_)->addr};
                                              ^
In file included from .pio\libdeps\teensy41\QNEthernet\src\QNEthernet.h:15:0,
                 from .pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:7:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:61:2: note: candidate: IPAddress::IPAddress(const uint8_t*)
  IPAddress(const uint8_t *address) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:61:2: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:58:2: note: candidate: IPAddress::IPAddress(uint32_t)
  IPAddress(uint32_t address) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:58:2: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:52:2: note: candidate: IPAddress::IPAddress(uint8_t, uint8_t, uint8_t, uint8_t)
  IPAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:52:2: note:   candidate expects 4 arguments, 1 provided
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:49:2: note: candidate: IPAddress::IPAddress()
  IPAddress() {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:49:2: note:   candidate expects 0 arguments, 1 provided
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note: candidate: constexpr IPAddress::IPAddress(const IPAddress&)
 class IPAddress : public Printable {
       ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note: candidate: constexpr IPAddress::IPAddress(IPAddress&&)
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note:   conversion of argument 1 would be ill-formed:
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp: In member function 'IPAddress qindesign::network::EthernetClass::broadcastIP() const':
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:322:44: error: 'const ip_addr_t {aka const struct ip_addr}' has no member named 'addr'
   return IPAddress{netif_ip_addr4(netif_)->addr |
                                            ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:323:48: error: 'const ip_addr_t {aka const struct ip_addr}' has no member named 'addr'
                    ~netif_ip_netmask4(netif_)->addr};
                                                ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:323:52: error: no matching function for call to 'IPAddress::IPAddress(<brace-enclosed initializer list>)'
                    ~netif_ip_netmask4(netif_)->addr};
                                                    ^
In file included from .pio\libdeps\teensy41\QNEthernet\src\QNEthernet.h:15:0,
                 from .pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:7:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:61:2: note: candidate: IPAddress::IPAddress(const uint8_t*)
  IPAddress(const uint8_t *address) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:61:2: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:58:2: note: candidate: IPAddress::IPAddress(uint32_t)
  IPAddress(uint32_t address) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:58:2: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:52:2: note: candidate: IPAddress::IPAddress(uint8_t, uint8_t, uint8_t, uint8_t)
  IPAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:52:2: note:   candidate expects 4 arguments, 1 provided
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:49:2: note: candidate: IPAddress::IPAddress()
  IPAddress() {
  ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:49:2: note:   candidate expects 0 arguments, 1 provided
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note: candidate: constexpr IPAddress::IPAddress(const IPAddress&)
 class IPAddress : public Printable {
       ^
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note:   conversion of argument 1 would be ill-formed:
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note: candidate: constexpr IPAddress::IPAddress(IPAddress&&)
C:\Users\XXX\.platformio\packages\framework-arduinoteensy\cores\teensy4/IPAddress.h:34:7: note:   conversion of argument 1 would be ill-formed:
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp: In member function 'void qindesign::network::EthernetClass::setLocalIP(const IPAddress&)':
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:333:35: error: cannot convert 'const ip_addr_t* {aka const ip_addr*}' to 'const ip4_addr_t* {aka const ip4_addr*}' for argument '2' to 'void netif_set_ipaddr(netif*, const ip4_addr_t*)'
   netif_set_ipaddr(netif_, &ipaddr);
                                   ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp: In member function 'void qindesign::network::EthernetClass::setSubnetMask(const IPAddress&)':
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:343:37: error: cannot convert 'const ip_addr_t* {aka const ip_addr*}' to 'const ip4_addr_t* {aka const ip4_addr*}' for argument '2' to 'void netif_set_netmask(netif*, const ip4_addr_t*)'
   netif_set_netmask(netif_, &netmask);
                                     ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp: In member function 'void qindesign::network::EthernetClass::setGatewayIP(const IPAddress&)':
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:353:27: error: cannot convert 'const ip_addr_t* {aka const ip_addr*}' to 'const ip4_addr_t* {aka const ip4_addr*}' for argument '2' to 'void netif_set_gw(netif*, const ip4_addr_t*)'
   netif_set_gw(netif_, &gw);
                           ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp: In member function 'bool qindesign::network::EthernetClass::joinGroup(const IPAddress&)':
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:369:50: error: cannot convert 'const ip_addr_t* {aka const ip_addr*}' to 'const ip4_addr_t* {aka const ip4_addr*}' for argument '2' to 'err_t igmp_joingroup_netif(netif*, const ip4_addr_t*)'
   return (igmp_joingroup_netif(netif_, &groupaddr) == ERR_OK);
                                                  ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp: In member function 'bool qindesign::network::EthernetClass::leaveGroup(const IPAddress&)':
.pio\libdeps\teensy41\QNEthernet\src\QNEthernet.cpp:378:51: error: cannot convert 'const ip_addr_t* {aka const ip_addr*}' to 'const ip4_addr_t* {aka const ip4_addr*}' for argument '2' to 'err_t igmp_leavegroup_netif(netif*, const ip4_addr_t*)'
   return (igmp_leavegroup_netif(netif_, &groupaddr) == ERR_OK);
                                                   ^
.pio\libdeps\teensy41\QNEthernet\src\QNEthernetClient.cpp: In member function 'IPAddress qindesign::network::EthernetClient::remoteIP()':
.pio\libdeps\teensy41\QNEthernet\src\QNEthernetClient.cpp:231:32: error: 'ip_addr_t {aka struct ip_addr}' has no member named 'addr'
   return state->pcb->remote_ip.addr;
                                ^
*** [.pio\build\teensy41\lib9da\QNEthernet\QNEthernet.cpp.o] Error 1
*** [.pio\build\teensy41\lib9da\QNEthernet\QNEthernetClient.cpp.o] Error 1
===================================================================== [FAILED] Took 4.53 seconds =====================================================================
 
I haven’t released it.

Side note: I don’t think PlatformIO gets the latest code once it’s seen code attached to a version. Once its library manager sees a specific version, it won’t update that same version until the version number changes. This means that it won’t pick up changes from GitHub within the same version.
 
I haven’t released it.

Side note: I don’t think PlatformIO gets the latest code once it’s seen code attached to a version. Once its library manager sees a specific version, it won’t update that same version until the version number changes. This means that it won’t pick up changes from GitHub within the same version.

Yes, PlatformIO is not connected to the Git version, it will display an update if the lib version counts up. I had some problems including the QNEthernet-lib in the lib/ directory of the PlatformIO project and I got it working via the library system of PlatformIO. The path and build system of PlatformIO is quite a little bit opaque

So how may I help with testing? Do you plan to make a branch?

My student is making progress with the testsetup and I have finished schematics and layout for a base board, so that I may have more hardware in the next two weeks. Currently we may test Teensy <--> Windows/Linux IPV6 UDP/RAW communication and later with more hardware Teensy <--> Teensy IPV6 UDP/RAW communication.
 
Try instead adding this to your lib_deps (and deleting any other QNEthernet/ under lib/ and .pio/libdeps/):
https://github.com/ssilverman/QNEthernet.git

When you have a board to test it with, message me.

I got my board with the ethernet interface back and started with a few tests.

First the current library with IPV6 configuration

platformio.ini
Code:
[env:teensy41]
platform = teensy
board = teensy41
framework = arduino
lib_deps = https://github.com/ssilverman/QNEthernet.git
build_flags = -D LWIP_IPV6=1

The lib with the latest changes is installed and the IPV6 config compiles :)

The second test was compiling the raw monitor example. This works and after flashing it shows some pakets from the home network. An IPV4 address shows up in the router list.

Sending a raw paket was not successful on the first try. I walked through the code an found the function that is actually sending the paket and added some more feedback. The result was, that I always got the result 0: the interface is not initialized. I hat a look in old build of the lib from last year.
Code:
  if (isInitialized) {
    return 0;
  }
was not present, so I uncommented this part. After that, the pakets are received with a direct connection and could be seen on wireshark. I tried to send frames to the Teensy but had no luck yet. I can see them on wireshark but not on the paket monitor of the example. I assume some firewall issues since it shows some received pakets but I'm still experimenting with it.

Code:
int enet_output_frame(const uint8_t *frame, size_t len) {
#if 0
  if (isInitialized) {
    return 0;
  }
#endif

  if (frame == NULL)  {
    return 1;
  }

  if ( len < 60){
    return 2;
  }
  
  if (MAX_FRAME_LEN - 4 < len){
    return 3;
  }

  volatile enetbufferdesc_t *bdPtr = get_bufdesc();
  memcpy(bdPtr->buffer, frame, len);
  update_bufdesc(bdPtr, len);
  return 4;
}
 
A few points:

1. Change defines in lwipopts.h instead of via build options in platformio.ini because lwIP may overwrite defines you put in the build command with the ones in the source code.
2. Because I've been making changes with the same version, "v0.14.0-snapshot", PlatformIO won't pick up anything new. Delete your .pio/libdeps/teensy41/QNEthernet directory and rebuild.
3. There's a fix for sending raw Ethernet frames. `if (isInitialized)` should have been `if (!isInitialized)`. Deleting and rebuilding per the previous point will pick up this fix and other fixes and changes.
 
Note that the EthernetFrame API won’t receive any known frame types. These include IP (including UDP and TCP) and ARP.
 
If you must use FNET it is a little bit more complicated to use the low level functions, but it is possible with a little bit of work. I've done it so I can walk you through it if need be, you can send raw frames without having to modify the library, but to receive raw frames you have to add the ethertype and a receive function to the fnet_eth_prot_if_list array.

Hi vjmuzik,

I used to send and receive raw frames using w5500(MACRAW mode) but it is not very fast. Can you give some steps about how to do it in FNET?
 
The W5500 has a built-in Ethernet stack that, as far as I understand, can’t be replaced. FNET is a software stack that operates at the same level as the stack on the W5500.
 
Back
Top