Martin
Martin

Reputation: 432

TCP cannot connect when routed, Raspberry Pi Pico + lwIP + ENC28J60

I use a Raspberry Pi Pico with a ENC28J60 PCB connected to one of its SPI. I use the pico-sdK downloaded 2023-11-29, and I use pico-enc28j60 downloaded from https://git.sr.ht/~krystianch/pico-enc28j60 on the same day. I had to modify CMakeLists.txt of enc28j60 project since lwIP was moved from Pico Extras to Pico SDK.

The initialization function looks like this:

static bool ethernet_init()
{
    err_t err;

    lwip_init();
    queue_init( &R.rx_queue, sizeof(struct pbuf *), ENC28J60_RX_QUEUE_SIZE );
    critical_section_init( &R.spi_cs );

    // initialize modbus clients
    for( int i=0; i<MODBUS_CLIENTS_MAX; i++ )
    {
        R.modbus_clients[i].tcp = 0;
        R.modbus_clients[i].state = ST_UNUSED;
        R.modbus_clients[i].seq_nr = (i << 12) | ((i << 8) ^ 0x0F00);
    }

    R.enc28j60.spi = spi1;
    R.enc28j60.cs_pin = SPI1_CSn_PIN;
    R.enc28j60.mac_address[0] = R.cfg.mac_addr[0];
    R.enc28j60.mac_address[1] = R.cfg.mac_addr[1];
    R.enc28j60.mac_address[2] = R.cfg.mac_addr[2];
    R.enc28j60.mac_address[3] = R.cfg.mac_addr[3];
    R.enc28j60.mac_address[4] = R.cfg.mac_addr[4];
    R.enc28j60.mac_address[5] = R.cfg.mac_addr[5];
    R.enc28j60.next_packet = 0;
    R.enc28j60.critical_section = &R.spi_cs;
    R.netif.name[0] = 'e';
    R.netif.name[1] = 'n';

    gpio_set_function( SPI1_SCK_PIN, GPIO_FUNC_SPI );
    gpio_set_function( SPI1_MOSI_PIN, GPIO_FUNC_SPI );
    gpio_set_function( SPI1_MISO_PIN, GPIO_FUNC_SPI );
    gpio_init( SPI1_CSn_PIN );
    gpio_put( SPI1_CSn_PIN, true );
    gpio_set_dir( SPI1_CSn_PIN, true );
    gpio_init( ETH_INT_PIN );
    gpio_init( ETH_RST_PIN );
    // reset the chip
    gpio_put( ETH_RST_PIN, false );
    gpio_set_dir( ETH_RST_PIN, true );
    sleep_ms( 1 );
    gpio_put( ETH_RST_PIN, true );
    spi_init( R.enc28j60.spi, SPI1_SPEED );

    netif_add( &R.netif, &R.cfg.ip_addr, &R.cfg.netmask, &R.cfg.gateway,
            &R.enc28j60, ethernetif_init, netif_input );
    netif_set_up( &R.netif );
    netif_set_link_up( &R.netif ); // +++ should check the enc if the link is up

    gpio_set_irq_enabled_with_callback( ETH_INT_PIN, GPIO_IRQ_EDGE_FALL,
                true, eth_irq );
    enc28j60_interrupts( &R.enc28j60,
                ENC28J60_PKTIE | ENC28J60_TXERIE | ENC28J60_RXERIE );

    R.tcp_modbus = tcp_new_ip_type( IPADDR_TYPE_V4 );
    err = tcp_bind( R.tcp_modbus, IP4_ADDR_ANY, TCP_PORT_MODBUS );
    if( err != ERR_OK )
    {
        return false;
    }
    R.tcp_modbus = tcp_listen_with_backlog( R.tcp_modbus, BACKLOG_MODBUS );
    if( !R.tcp_modbus )
    {
        return false;
    }
    tcp_accept( R.tcp_modbus, modbus_accept );
    return true;
}

On the local network everything works fine. I can ping it, I can connect to the TCP port and do modbus queries, works perfect.

But when put a router between the computer and the Pico I get problems. Ping still works fine, but I get no TCP connects. I can see the SYN packets going towards the Pico but I see no SYN/ACK coming back. I put a printf into the modbus_accept function to see if it is called, but it is not called at all.

I believe the pico-enc28j60 works fine since there are no problems on the local network, and also since the ping over the router works too.

I believe the interface is configured correctly since ping is routed fine.

So I believe there must be a problem either in my code or in lwIP. I just can't see what is wrong.

Any hints?

Upvotes: 0

Views: 148

Answers (1)

Martin
Martin

Reputation: 432

After digging and debugging through the lwIP source code if found out that netif_default was NULL. Calling netif_set_default solves the problem.

The same thing was recommended in this email: https://lists.nongnu.org/archive/html/lwip-users/2012-03/msg00083.html

Upvotes: 0

Related Questions