FreeRTOS +TCP on SAME70

Rather than append to some related, existing posts, I figured I’d start a new thread regarding successfully setting up +TCP on the SAME70 platform. Before I jump into what I’ve done, where I’m up to and the related code, below is what I’m trying to achieve:

  • SAME70 is configured as a TCP server. The server will only ever connect with a single client (see second point below).

  • SAME70 is connected directly to a CPU (i.e. no router or network involved). As such, a static IP address is to be used, with DHCP and DNS not required.

  • The SAME70 will routinely send data out on the wire. This will eventually be driven by hardware NVIC IRQ, but for testing purposes I’ll use a SysTick event to send dummy data every x milliseconds.

  • The SAME70 will occasionally receive data from the client (mainly configuration changes).

What I’ve done
I created a new project in Atmel Studio based on ASF 3.47.0, and incorporated both FreeRTOS 10.3.0 and +TCP 2.2.1. Hein very kindly provided SAME70 driver files in this post, which have also been added to the project. Note that the ASF ethernet drivers were not added to the project.

Where I’m up to
I’m able to compile the project without issue, and the software is running on the SAME70. However, there is an issue with PHY configuration, as the attached PHY (a KSZ8081RN) is not found in the xPhyDiscover function. I’ve bypassed the function for the time being, setting the PHY address and ID values manually. Auto-negotiation appears to work (given the console output), but the link doesn’t appear to go up. I’ve added a printf() statement in xPhyCheckLinkStatus() which shows the xLinkStatusTimer is firing every second (per ipconfigPHY_LS_LOW_CHECK_TIME_MS), indicating the link status never goes high. I’ve bypassed xPhyDiscover purely for testing purposes, the fact the PHY isn’t found in xPhyDiscover is indicative of the actual problem, and needs to be addressed.

Rather than posting hundreds of lines of code, I figured I’d post only sections of files which have been modified/configured thus far. I’ll start with the PHY pin definitions, which are in my board definition header:

/* KSZ8081RN pin definition */
#define PIN_KSZ8081RN_TXD0_IDX                PIO_PD2_IDX
#define PIN_KSZ8081RN_TXD0_FLAGS              (IOPORT_MODE_MUX_A)
#define PIN_KSZ8081RN_TXD1_IDX                PIO_PD3_IDX
#define PIN_KSZ8081RN_TXD1_FLAGS              (IOPORT_MODE_MUX_A)
#define PIN_KSZ8081RN_CRS_DV_IDX              PIO_PD4_IDX
#define PIN_KSZ8081RN_CRS_DV_FLAGS            (IOPORT_MODE_MUX_A)
#define PIN_KSZ8081RN_RXER_IDX                PIO_PD7_IDX
#define PIN_KSZ8081RN_RXER_FLAGS              (IOPORT_MODE_MUX_A)
#define PIN_KSZ8081RN_REFLCK_IDX              PIO_PD0_IDX
#define PIN_KSZ8081RN_REFCLK_FLAGS            (IOPORT_MODE_MUX_A)
#define PIN_KSZ8081RN_RXD0_IDX                PIO_PD5_IDX
#define PIN_KSZ8081RN_RXD0_FLAGS              (IOPORT_MODE_MUX_A)
#define PIN_KSZ8081RN_RXD1_IDX                PIO_PD6_IDX
#define PIN_KSZ8081RN_RXD1_FLAGS              (IOPORT_MODE_MUX_A)
#define PIN_KSZ8081RN_MDC_IDX                 PIO_PD8_IDX
#define PIN_KSZ8081RN_MDC_FLAGS               (IOPORT_MODE_MUX_A)
#define PIN_KSZ8081RN_MDIO_IDX                PIO_PD9_IDX
#define PIN_KSZ8081RN_MDIO_FLAGS              (IOPORT_MODE_MUX_A)
#define PIN_KSZ8081RN_TXEN_IDX                PIO_PD1_IDX
#define PIN_KSZ8081RN_TXEN_FLAGS              (IOPORT_MODE_MUX_A)
#define PIN_KSZ8081RN_RESET_IDX               PIO_PC10_IDX
#define PIN_KSZ8081RN_INTRP_IDX               PIO_PA14_IDX

The pins are configured in my board init.c file, which is called from board_init() in my main.c main() function:

/* Configure PHY pins */
ioport_set_pin_peripheral_mode(PIN_KSZ8081RN_TXD0_IDX, PIN_KSZ8081RN_TXD0_FLAGS);
ioport_set_pin_peripheral_mode(PIN_KSZ8081RN_TXD1_IDX, PIN_KSZ8081RN_TXD1_FLAGS);
ioport_set_pin_peripheral_mode(PIN_KSZ8081RN_CRS_DV_IDX, PIN_KSZ8081RN_CRS_DV_FLAGS);
ioport_set_pin_peripheral_mode(PIN_KSZ8081RN_RXER_IDX, PIN_KSZ8081RN_RXER_FLAGS);
ioport_set_pin_peripheral_mode(PIN_KSZ8081RN_REFLCK_IDX, PIN_KSZ8081RN_REFCLK_FLAGS);
ioport_set_pin_peripheral_mode(PIN_KSZ8081RN_RXD0_IDX, PIN_KSZ8081RN_RXD0_FLAGS);
ioport_set_pin_peripheral_mode(PIN_KSZ8081RN_RXD1_IDX, PIN_KSZ8081RN_RXD1_FLAGS);
ioport_set_pin_peripheral_mode(PIN_KSZ8081RN_MDC_IDX, PIN_KSZ8081RN_MDC_FLAGS);
ioport_set_pin_peripheral_mode(PIN_KSZ8081RN_MDIO_IDX, PIN_KSZ8081RN_MDIO_FLAGS);
ioport_set_pin_peripheral_mode(PIN_KSZ8081RN_TXEN_IDX, PIN_KSZ8081RN_TXEN_FLAGS);

/* Configure PHY GPIO pins */
ioport_set_pin_dir(PIN_KSZ8081RN_INTRP_IDX, IOPORT_DIR_INPUT);
ioport_set_pin_dir(PIN_KSZ8081RN_RESET_IDX, IOPORT_DIR_OUTPUT);

Other than that, I enable the various peripheral clocks in main(), then initialise FreeRTOS_IP via FreeRTOS_IPInit as per the +TCP tutorial. Other than a few minor formatting changes, and replacing sysclk_get_cpu_hz() with sysclk_get_peripheral_hz() in gmac_set_mdc_clock() in prvGMACInit(), everything has been left more or less as is.

Is there an obvious starting place in determining why the PHY can’t be found?

Any input or guidance would be greatly appreciated!

I’m adding some further information as I go, in the hopes that someone else looking to utilise +TCP on their SAME70-based project in the future might find it useful.

I’ve done a line-by-line review of the PHY configuration and initialisation processes, comparing the ASF lwIP-based files with +TCP. I still don’t understand why the PHY isn’t found. Below is the prvGMACInit() function, which is almost unchanged from the latest SAME70 NetworkInterface.c file:

static BaseType_t prvGMACInit( void )
{
uint32_t ncfgr;

    gmac_options_t gmac_option;

	gmac_enable_management(GMAC, true);
	/* Enable further GMAC maintenance. */
	GMAC->GMAC_NCR |= GMAC_NCR_MPE;

	memset( &gmac_option, '\0', sizeof( gmac_option ) );
	gmac_option.uc_copy_all_frame = 0;
	gmac_option.uc_no_boardcast = 0;
	memcpy( gmac_option.uc_mac_addr, ucMACAddress, sizeof( gmac_option.uc_mac_addr ) );

	gs_gmac_dev.p_hw = GMAC;
	gmac_dev_init( GMAC, &gs_gmac_dev, &gmac_option );

	NVIC_SetPriority( GMAC_IRQn, configMAC_INTERRUPT_PRIORITY );
	NVIC_EnableIRQ( GMAC_IRQn );

	{
		/* Set MDC clock divider. */
		gmac_set_mdc_clock( GMAC, sysclk_get_cpu_hz() );

		vPhyInitialise( &xPhyObject, xPHY_Read, xPHY_Write );
		while(xPhyDiscover( &xPhyObject ) < 1);
		xPhyConfigure( &xPhyObject, &xPHYProperties );

		/* For a reset / reconfigure of the EMAC. */
		prvEthernetUpdateConfig( pdTRUE );

		/* Select Media Independent Interface type */
		#if( SAME70 != 0 )
		{
			/* Selecting RMII mode. */
			GMAC->GMAC_UR &= ~GMAC_UR_RMII;
		}
		#else
		{
			gmac_select_mii_mode(GMAC, ETH_PHY_MODE);
		}
		#endif

		gmac_enable_transmit(GMAC, true);
		gmac_enable_receive(GMAC, true);

	}

	gmac_enable_management(GMAC, true);

	gmac_set_address( GMAC, 1, (uint8_t*)llmnr_mac_address );

	gmac_enable_management(GMAC, false);
	/* Disable further GMAC maintenance. */
	GMAC->GMAC_NCR &= ~GMAC_NCR_MPE;

	return 1;
}

The only change I’ve made, is putting xPhyDiscover( &xPhyObject) in a while loop, to allow for the possibility of the PHY not quite being ready. All I’ve done within xPhyDiscover() is add a printf() to monitor the value of ulLowerID from the PHY ID2 register (register 3h):

BaseTytpe_t xPhyDiscover( EthernetPhy_t *pxPhyObject)
{
BaseType_t xPhyAddress;

    pxPhyObject->xPortCount = 0;

    for( xPhyAddress = phyMIN_PHY_ADDRESS; xPhyAddress <= phyMAX_PHY_ADDRESS; xPhyAddress++ )
    {
    uint32_t ulLowerID;

        pxPhyObject->fnPhyRead( xPhyAddress, phyREG_03_PHYSID2, &ulLowerID);
        printf("phyREG_03_PHYSID2: %#08x\r\n", ulLowerID);

The resulting console output is perpetual output of the following:

phyREG_03_PHYSID2: 0x00ffff

Per Hein’s post here, I believe I have the required clocks configured and enabled, the EMAC setup hasn’t been changed from the provided SAME70 files, the pin muxing has been performed and was listed in my original post, and RMII has been selected (per the above prvGMACInit function).

Is there anything else I’m missing?

I just tested my SAME70 board again, and it worked fine with the DriverSAM.

The PHY was detected immediately at slot-0.

What hardware are you using? Is it a SAM E70 Xplained evaluation kit? Or a different board?

1 Like

That’s quite strange! Yes, I’m also using the SAM E70 Xplained kit. Which FreeRTOS, +TCP and ASF versions are you using?

We must have different ASF configurations, because the following line in NetworkInterface.c causes an invalid MDC clock divider:

gmac_set_mdc_clock( GMAC, sysclk_get_cpu_hz() );

The SAME70 should be (or at least it usually is) running at 300Mhz, gmac_set_mdc_clock() would result in GMAC_INVALID:

static inline uint8_t gmac_set_mdc_clock(Gmac* p_gmac, uint32_t ul_mck)
{
    uint32_t ul_clk, ul_value;

    if (ul_mck > GMAC_MCK_SPEED_240MHZ) {
        return GMAC_INVALID;

Using sysclk_get_peripheral_clk() works fine, but I’m still unable to find the PHY.

Would it be possible for you to share your .atsln project? It would probably identify where mine is failing pretty easily.

Good news that you are working with the same X-plained board.

My main() calls:

    sysclk_init();
    board_init();                    /* See init.c */
    heapInit();                      /* Make sure pvPortMalloc() can work. */
    pmc_enable_periph_clk(ID_GMAC);  /* Enabled peripheral clock. */
    vEthernetInit();                 /* See below. */

Have you called pmc_enable_periph_clk() as well ?

My sysclk_get_peripheral_hz() returns 75,000,000
And sysclk_get_main_hz() returns 300,000,000

Please find here some config files that I use:
config_same70_hein.zip (10.6 KB)

static void vEthernetInit()
{
    pio_set_output(PIN_GMAC_RESET_PIO, PIN_GMAC_RESET_MASK, 1,  false, true);
    pio_set_input(PIN_GMAC_INT_PIO, PIN_GMAC_INT_MASK, PIO_PULLUP);
    pio_set_peripheral(PIN_GMAC_PIO, PIN_GMAC_PERIPH, PIN_GMAC_MASK);

    /* Configure GMAC runtime clock */
    gmac_set_mdc_clock(GMAC, sysclk_get_cpu_hz());
    /* Enable GMAC clock */
}

I don’t see any occurrence of sysclk_get_peripheral_clk().

Thank you very much Hein, your support is extremely appreciated. A couple of comments:

  1. Are you using heap_4? If so, would you mind detailing your heapInit() function, as the SAM4E example uses heap_5 which has a slightly different setup (as you’d obviously know).

  2. The conf_eth.h file you included in the zip folder; is that definitely for/used in your SAM E70 Xplained project? The settings in there are for an SPI-based combined MAC/PHY, which isn’t used on the Xplained board (KSZ8851SNL vs. the Xplained’s KZS8081).

  3. The rest of your configuration makes sense, so I’m hoping that getting the heap_4 setup properly will be a good next step.

Thanks!

  1. Are you using heap_4?

Although the algorithm is the same, I prefer to use heap_5.

The actual free amount of RAM available, is only known after linking the project. The heap space starts were the data segments end, and it ends where the main stack begins.

I used pseudo variables which are defined in my linker script:

extern uint8_t __bss_end__, _estack, _Min_Stack_Size;
#define HEAP_START		__bss_end__
#define HEAP_END		_estack

volatile uint32_t ulHeapSize;
volatile uint8_t *pucHeapStart;

static void heapInit( )
{
uint32_t ulStackSize = (uint32_t)&(_Min_Stack_Size);

    pucHeapStart = ( uint8_t * ) (((( uint32_t)&HEAP_START) + 7) & ~0x07ul);

    ulHeapSize = ( uint32_t ) ( &HEAP_END - &HEAP_START );
    ulHeapSize &= ~0x07ul;
    ulHeapSize -= ulStackSize;

    HeapRegion_t xHeapRegions[] = {
        { ( unsigned char *) pucHeapStart, ulHeapSize },
        { NULL, 0 }
    };

    vPortDefineHeapRegions( xHeapRegions );
}

  1. The settings in there are for an SPI-based combined MAC/PHY

I used 2 EMAC/PHY’s in this project: one through SPI, and the EMAC peripheral. I needed a second interface to test FreeRTPS+TCP /multi.
You won’t need SPI to set-up Ethernet.

About FreeRTOS+TCP has a pool of ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS network buffers.

A zero-copy driver passes the pointers of these buffers directly to the DMA. DriverSAM allocates GMAC_RX_BUFFERS network buffer for DMA reception in advance.
As for outgoing traffic, at most GMAC_TX_BUFFERS buffers are needed simultaneously.

UDP-sockets keep network packets in their buffer until they are read by the user ( by calling FreeRTOS_recvfrom() ).

It is important to tune these numbers well. I tend to log the actual usage ( calling uxGetMinimumFreeNetworkBuffers() ).

And so, when zero-copy is being used, the following equation must be true:

ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS > ( GMAC_TX_BUFFERS + GMAC_RX_BUFFERS + SPARE )

To suggest a practical example:

    #define GMAC_TX_BUFFERS                           2
    #define GMAC_RX_BUFFERS                           4
    #define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS   16

Why do I write this? In my SAME70 testing project, I had a bad configuration, because GMAC_RX_BUFFERS > ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS.
This caused an assert during startup.

The above macro’s must be defined in your project’s FreeRTOSIPConfig.h file.

Hello Hein,

thank you for your help, but your configuration files didn’t work either.
Could you please build a small solution with your driver that works on your end, so I could compare them with mine or try it with my board? Without the modifications i posted on the other topic, i can’t even get your driver to recognise the PHY.
Thank you very much in advance!

Thank you Hein, I spent most of last night going through the detail of heap_5.c, and learning how the linker script should be setup. I’ve now got a solid heap initialisation function, with some reasonable stack and heap sizes. I’ll no doubt need to adjust these in due course, but for the time being they’re ok.

I’ve had some success with the PHY as well! xPhyDiscover() now finds the KSZ8081 at address 0 as expected; I can’t pinpoint exactly which change fixed the issue, as I was reorganising and changing bits and pieces across multiple files.

My next issue, is that despite the PHY being initialised, and the LAN port LED (green) flashing, the PHY link status never goes high. Below is the console output on reset; the ethernet cable is connected prior to reset (i.e. the cable is always plugged in).

prvIPTask started
Event received: 0
PHY ID 221560
xPhyReset: phyBMCR_RESET 0 ready
+TCP: advertise: 01E1 config 3100
prvEthernetUpdateConfig: LS mask 00 Force 1
Autonego ready: 0000786d: full duplex 100 mbit high status
Network buffers: 44 lowest 44
Network up event.
Link status low - pxPhyObject->ulLinkStatusMask: 0
Network buffers: 43 lowest 43
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0

The ‘Network up event.’ is a puts() statement I added to the vApplicationIPNetworkEventHook() callback in my main.c file:

void vApplicationIPNetworkEventHook(eIPCallbackEvent_t eNetworkEvent)
{
	static BaseType_t xTasksAlreadyCreated = pdFALSE;
	
	/* Check whether the network event is a 'network up' or 'network down' event */
	if (eNetworkEvent == eNetworkUp) {

        puts("Network up event.\r\n");
		
		/* Check whether the TCP/IP tasks have already been created */
		if (xTasksAlreadyCreated == pdFALSE) {
			
			/* Call the vCreateTCPServerSocket task */
			vCreateTCPServerSocket();
			
		}
		
	} else {

        puts("Network down event.");

    }
}

The ‘Link Status low - pxPhyObject->ulLinkStatusMask: 0’ line is a printf statement I added at the bottom of xPhyCheckLinkStatus() in phyHandling.c:

vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) );
if( ( pxPhyObject->ulLinkStatusMask & phyBMSR_LINK_STATUS ) != 0 )
{
	/* The link status is high, so don't poll the PHY too often. */
	pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
}
else
{
	/* The link status is low, polling may be done more frequently. */
	printf("Link status low - pxPhyObject->ulLinkStatusMask: %d\r\n", pxPhyObject->ulLinkStatusMask & phyBMSR_LINK_STATUS);
	pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_LOW_CHECK_TIME_MS );
}

Given that the network is reportedly ‘up’, why does the PHY link status never go up as well? Where should I be looking to try and resolve this issue?

Hello jars,

please have a look at my patch here, with this i could get the PHY initialized and correctly find the connection status and also had auto-negotiation working. It didn’t transfer anything, though. Could you please test, if you’ve got the same problem? Thank you!

Thanks for that PBot, I’ve largely got the same patch applied in my code as well. I can both find the PHY and complete auto-negotiation, but the link status is never high. I suspect you’re one step ahead of me, as it sounds like you do achieve a high link status, but can then not send out on the wire?

Are you sure your link status is high? Do you have a printf() or similar statement in xPhyCheckLinkStatus()? That may be a stupid question, but it would make sense that you can’t send data out if the PHY link isn’t actually high.

No, i think you’re right, the check for link status returns low for me, too.

What’s confusing is, the system seems to detect a difference though when probing for the connection status. Here’s with my ethernet cable plugged in (running the ECHO test):

FreeRTOS_IPInit
vTaskStartScheduler
prvIPTask started
prvEthernetUpdateConfig: LS mask 00 Force 1
PHY ID 221560
xPhyReset: phyBMCR_RESET 0 ready
+TCP: advertise: 01E1 config 3100
Network buffers: 17 lowest 17
Link status low - pxPhyObject->ulLinkStatusMask: 0
Network buffers: 16 lowest 16
Link status low - pxPhyObject->ulLinkStatusMask: 0
xPhyCheckLinkStatus: PHY LS now 01
Link status low - pxPhyObject->ulLinkStatusMask: 0
prvEthernetUpdateConfig: LS mask 01 Force 0
vApplicationIPNetworkEventHook: event 1
prvInitialiseDHCP: start after 250 ticks
vDHCPProcess: discover
Autonego ready: 0000786d: full duplex 100 mbit high status
Network buffers: 15 lowest 15
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
vDHCPProcess: discover
vDHCPProcess: timeout 10000 ticks
Network buffers: 14 lowest 14
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
vDHCPProcess: discover
vDHCPProcess: timeout 20000 ticks
Network buffers: 13 lowest 13
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
xPhyCheckLinkStatus: PHY LS now 00
Link status low - pxPhyObject->ulLinkStatusMask: 0
prvEthernetUpdateConfig: LS mask 00 Force 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
vDHCPProcess: giving up 40000 > 30000 ticks
vApplicationIPNetworkEventHook: event 0
IP Address: 192.168.42.35
Subnet Mask: 255.255.255.0
Gateway Address: 192.168.42.1
DNS Server Address: 192.168.42.1
Socket 7 -> 0ip:0 State eCLOSED->eTCP_LISTEN
FreeRTOS_connect: 17724 to c0a82afcip:7
Socket 17724 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
Network buffers: 13 lowest 12

And here with the cable removed:

FreeRTOS_IPInit
vTaskStartScheduler
prvIPTask started
prvEthernetUpdateConfig: LS mask 00 Force 1
PHY ID 221560
xPhyReset: phyBMCR_RESET 0 ready
+TCP: advertise: 01E1 config 3100
Network buffers: 17 lowest 17
Link status low - pxPhyObject->ulLinkStatusMask: 0
Network buffers: 16 lowest 16
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
vApplicationIPNetworkEventHook: event 1
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
vApplicationIPNetworkEventHook: event 1
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
vApplicationIPNetworkEventHook: event 1
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
vApplicationIPNetworkEventHook: event 1
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
vApplicationIPNetworkEventHook: event 1
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
vApplicationIPNetworkEventHook: event 1
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
vApplicationIPNetworkEventHook: event 1
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
vApplicationIPNetworkEventHook: event 1
Link status low - pxPhyObject->ulLinkStatusMask: 0

As you can see, with the cable plugged in, there’s a successful auto negotiation and the system begins to try and submit packages, but fails. With the cable unplugged, no auto negotiation happens and the system waits for the cable to be plugged in (when plugging it in in this state, it also successfully detects it and reaches auto negotiation).

To test this on your side, could you please enable ipconfigETHERNET_AN_ENABLE in your FreeRTOSIPConfig.h and look for a “Autonego ready:” line in your debug output?

EDIT:

I can’t seem to add another answer to this topic (what’s the reasoning behind that??), so here’s some further investigation:

I’ve been digging around in the xPhyCheckLinkStatus function, and I think what we’re seeing is a false negative. The check that returned 0 is just used for determining how often the link should be checked. Also, i think there’s a small error in the logic.
I’ve modified the function like this:

BaseType_t xPhyCheckLinkStatus( EthernetPhy_t *pxPhyObject, BaseType_t xHadReception )
{
uint32_t ulStatus, ulBitMask = 1u;
BaseType_t xPhyIndex;
BaseType_t xNeedCheck = pdFALSE;

	if( xHadReception > 0 )
	{
		/* A packet was received. No need to check for the PHY status now,
		but set a timer to check it later on. */
		vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) );
		pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
		for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
		{
			if( ( pxPhyObject->ulLinkStatusMask & ulBitMask ) == 0ul )
			{
				pxPhyObject->ulLinkStatusMask |= ulBitMask;
				FreeRTOS_printf( ( "xPhyCheckLinkStatus: PHY LS now %02lX\n", pxPhyObject->ulLinkStatusMask ) );
				xNeedCheck = pdTRUE;
			}
		}
	}
	else if( xTaskCheckForTimeOut( &( pxPhyObject->xLinkStatusTimer ), &( pxPhyObject->xLinkStatusRemaining ) ) != pdFALSE )
	{
		/* Frequent checking the PHY Link Status can affect for the performance of Ethernet controller.
		As long as packets are received, no polling is needed.
		Otherwise, polling will be done when the 'xLinkStatusTimer' expires. */
		for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
		{
		BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];

			if( pxPhyObject->fnPhyRead( xPhyAddress, phyREG_01_BMSR, &ulStatus ) == 0 )
			{
				if( !!( pxPhyObject->ulLinkStatusMask & ulBitMask ) != !!( ulStatus & phyBMSR_LINK_STATUS ) )
				{
					if( ( ulStatus & phyBMSR_LINK_STATUS ) != 0 )
					{
						pxPhyObject->ulLinkStatusMask |= ulBitMask;
					}
					else
					{
						pxPhyObject->ulLinkStatusMask &= ~( ulBitMask );
					}
					FreeRTOS_printf( ( "xPhyCheckLinkStatus: PHY LS now %02lX\n", pxPhyObject->ulLinkStatusMask ) );
					xNeedCheck = pdTRUE;
				}
			}
		}
		vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) );
		if( ( pxPhyObject->ulLinkStatusMask & ( ulBitMask >> 1 ) ) != 0 )
		{
			/* The link status is high, so don't poll the PHY too often. */
			printf( "Link status high - pxPhyObject->ulLinkStatusMask: %d\r\n", pxPhyObject->ulLinkStatusMask );
			pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
		}
		else
		{
			/* The link status is low, polling may be done more frequently. */
			printf( "Link status low - pxPhyObject->ulLinkStatusMask: %d\r\n", pxPhyObject->ulLinkStatusMask );
			pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_LOW_CHECK_TIME_MS );
		}
	}
	return xNeedCheck;
}

And now it reacts correctly to the status change and polls less often. Also, if i remove the cable and plug it back in the reaction is also correct.

FreeRTOS_IPInit
vTaskStartScheduler
prvIPTask started
prvEthernetUpdateConfig: LS mask 00 Force 1
PHY ID 221560
xPhyReset: phyBMCR_RESET 0 ready
+TCP: advertise: 01E1 config 3100
Network buffers: 17 lowest 17
Link status low - pxPhyObject->ulLinkStatusMask: 0
Network buffers: 16 lowest 16
Link status low - pxPhyObject->ulLinkStatusMask: 0
xPhyCheckLinkStatus: PHY LS now 01
Link status high - pxPhyObject->ulLinkStatusMask: 1
prvEthernetUpdateConfig: LS mask 01 Force 0
vApplicationIPNetworkEventHook: event 1
prvInitialiseDHCP: start after 250 ticks
vDHCPProcess: discover
Autonego ready: 0000786d: full duplex 100 mbit high status
Network buffers: 15 lowest 15
vDHCPProcess: discover
vDHCPProcess: timeout 10000 ticks
Network buffers: 14 lowest 14
Link status high - pxPhyObject->ulLinkStatusMask: 1
vDHCPProcess: discover
vDHCPProcess: timeout 20000 ticks
Network buffers: 13 lowest 13
Link status high - pxPhyObject->ulLinkStatusMask: 1
vDHCPProcess: giving up 40000 > 30000 ticks
vApplicationIPNetworkEventHook: event 0
IP Address: 192.168.42.35
Subnet Mask: 255.255.255.0
Gateway Address: 192.168.42.1
DNS Server Address: 192.168.42.1
Socket 7 -> 0ip:0 State eCLOSED->eTCP_LISTEN
FreeRTOS_connect: 17724 to c0a82afcip:7
Socket 17724 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
Network buffers: 12 lowest 12
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
Network buffers: 11 lowest 11
Network buffers: 10 lowest 10
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Network buffers: 9 lowest 9
Network buffers: 0 lowest 0
Connect: giving up c0a82afcip:7
Socket 17724 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
FreeRTOS_closesocket[17724 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 24121 to c0a82afcip:7
Socket 24121 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Connect: giving up c0a82afcip:7
Socket 24121 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
FreeRTOS_closesocket[24121 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 8336 to c0a82afcip:7
Socket 8336 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
Link status high - pxPhyObject->ulLinkStatusMask: 1
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Connect: giving up c0a82afcip:7
Socket 8336 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
FreeRTOS_closesocket[8336 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 24503 to c0a82afcip:7
Socket 24503 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Connect: giving up c0a82afcip:7
Socket 24503 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
FreeRTOS_closesocket[24503 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 7276 to c0a82afcip:7
Socket 7276 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Connect: giving up c0a82afcip:7
Socket 7276 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
FreeRTOS_closesocket[7276 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 4626 to c0a82afcip:7
Socket 4626 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Connect: giving up c0a82afcip:7
Socket 4626 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
Link status high - pxPhyObject->ulLinkStatusMask: 1
FreeRTOS_closesocket[4626 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 6273 to c0a82afcip:7
Socket 6273 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Connect: giving up c0a82afcip:7
Socket 6273 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
FreeRTOS_closesocket[6273 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 13970 to c0a82afcip:7
Socket 13970 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Connect: giving up c0a82afcip:7
Socket 13970 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
FreeRTOS_closesocket[13970 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 4090 to c0a82afcip:7
Socket 4090 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Connect: giving up c0a82afcip:7
Socket 4090 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
FreeRTOS_closesocket[4090 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 22629 to c0a82afcip:7
Socket 22629 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
xPhyCheckLinkStatus: PHY LS now 00
Link status low - pxPhyObject->ulLinkStatusMask: 0
prvEthernetUpdateConfig: LS mask 00 Force 0
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Connect: giving up c0a82afcip:7
Socket 22629 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
FreeRTOS_closesocket[22629 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 8483 to c0a82afcip:7
Socket 8483 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
Link status low - pxPhyObject->ulLinkStatusMask: 0
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Connect: giving up c0a82afcip:7
Socket 8483 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
FreeRTOS_closesocket[8483 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 24071 to c0a82afcip:7
Socket 24071 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
Link status low - pxPhyObject->ulLinkStatusMask: 0
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Connect: giving up c0a82afcip:7
Socket 24071 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
FreeRTOS_closesocket[24071 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 24581 to c0a82afcip:7
Socket 24581 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
Link status low - pxPhyObject->ulLinkStatusMask: 0
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Link status low - pxPhyObject->ulLinkStatusMask: 0
Connect: giving up c0a82afcip:7
Socket 24581 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
Link status low - pxPhyObject->ulLinkStatusMask: 0
Link status low - pxPhyObject->ulLinkStatusMask: 0
FreeRTOS_closesocket[24581 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 32301 to c0a82afcip:7
Socket 32301 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
Link status low - pxPhyObject->ulLinkStatusMask: 0
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Link status low - pxPhyObject->ulLinkStatusMask: 0
Connect: giving up c0a82afcip:7
Socket 32301 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
xPhyCheckLinkStatus: PHY LS now 01
Link status high - pxPhyObject->ulLinkStatusMask: 1
prvEthernetUpdateConfig: LS mask 01 Force 0
FreeRTOS_closesocket[32301 to c0a82afcip:7]: buffers 0 socks 1
Autonego ready: 0000786d: full duplex 100 mbit high status
FreeRTOS_connect: 15158 to c0a82afcip:7
Socket 15158 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Connect: giving up c0a82afcip:7
Socket 15158 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
FreeRTOS_closesocket[15158 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 26333 to c0a82afcip:7
Socket 26333 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Connect: giving up c0a82afcip:7
Socket 26333 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT
FreeRTOS_closesocket[26333 to c0a82afcip:7]: buffers 0 socks 1
FreeRTOS_connect: 2126 to c0a82afcip:7
Socket 2126 -> c0a82afcip:7 State eCLOSED->eCONNECT_SYN
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 1: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 2: 500 ms
ARP for c0a82afcip (using c0a82afcip): rc=0 00:00:00 00:00:00
Connect[c0a82afcip:7]: next timeout 3: 500 ms
Connect: giving up c0a82afcip:7
Socket 2126 -> c0a82afcip:7 State eCONNECT_SYN->eCLOSE_WAIT

So it’s pretty sure not the cause of the unability to send or receive packets.
I’ll dig further and see, if i can find anything.

EDIT 2:

I think i’ve found part of the problem.
gmac_dev_write checks if there’s TX buffers available by comparing
if ((p_tx_td->status.val & GMAC_TXD_USED) == 0)
which always returns 0, as the “status.val” member of all entries in gs_tx_desc are 0 (instead of 1ul << 31, as they should be).

Further looking at gmac_reset_tx_mem the line
gs_tx_desc[ul_index].status.val = GMAC_TXD_USED;
does nothing, after that, status.val is still 0, so the memory is not written.

To test that, i removed the
__attribute__ ((section(".first_data")))
from the variable declarations for ucNetworkPackets, gs_tx_desc, gs_tx_desc_null and gs_rx_desc, and gmac_dev_write stops returning GMAC_TX_BUSY as the variable contents can now be changed.
But that’s just treatment of symptoms, not the cause, as the packets still can’t get sent out.
gmac_start_transmission gets called, but doesn’t actually change the GMAC_NCR register.
I’ll have to dig deeper tomorrow, i think maybe it’s all related to the buffers?

Great work PBot, you’ve certainly uncovered a few things there. I’ve made the change to the xPhyCheckLinkStatus() function as per your inclusion above, and it does indeed seem to be working now. When the cable is plugged in, the console prints ‘status high’ every 15 seconds. When I remove the cable (while the program is still running), the console prints ‘status low’ every second, which is the expected behaviour. Similarly, when the cable is then plugged back in, it reverts to ‘status high’ every 15 seconds.

I’m actually not using the TCP echo example, I’ve put together a main.c which follows the TCP networking tutorial. As such, while the status link is now correct, my program never accepts an incoming connection request. This is part of my vCreateTCPServerSocket() function which is called when the eNetworkUp event is initially handled:

for ( ;; )
{
    xConnectedSocket = FreeRTOS_accept(xListeningSocket, &xClient, &xSize);
    configASSERT(xConnectedSocket != FREERTOS_INVALID_SOCKET);

    xTaskCreate(prvConnManagement, "TCPServer", SERVER_STACK_SIZE, (void *) xConnectedSocket, tskIDLE_PRIORITY, NULL);

}

The preceding code creates the socket, sets the socket options, binds the socket to an address and port, and then listens for connection requests. All of that was taken directly from the +TCP network tutorial linked above. My issue is that the prvConnManagement() function is never called.

I suspect I’ll have the exact same send() issues as you once I’ve got a connection established, but for the time being I need to understand why a connection isn’t being made. I’ll continue to look through my code today and hopefully report back this evening.

I’ve done some investigating, and have found an issue in the FreeRTOS_bind() process. At the bottom of FreeRTOS_bind(), once the socket has been validated, the socket has been checked that it isn’t already bound and the xSendEventStructToIPTask() has succeeded, xEventGroupWaitBits() is called to wait until the eSOCKET_BOUND bit is set.

Halfway down xEventGroupWaitBits(), at approximately line 397, we have this:

xAlreadyYielded = xTaskResumeAll();

if ( xTicksToWait != ( TickType_t ) 0 )
{
    if ( xAlreadyYielded == pdFALSE )
    {
        printf("Attempting yield...\r\n");
        portYIELD_WITHIN_API();
    }
    else
    {
        mtCOVERAGE_TEST_MARKER();
    }

    printf("Yield complete.\r\n);

I’ve obviously added the above printf() statements. I’m finding that this xEventGroupWaitBits() function is getting stuck in portYIELD_WITHIN_API(), as “Attempting yield…” is printed to the console, but I never reach “Yield complete.”. Having done some initial research, I’ve tried both enabling and disabling configUSE_TICKLESS_IDLE, which made no difference. What are the likely causes for this issue? I’ve followed the +TCP network tutorial in setting up the various tasks, so while it shouldn’t be an interrupt issue, it probably is?

EDIT: It looks like I was at least partially correct. I’ve increased the task priority of the socket initialisation task, and have had some success in getting the socket binding setup. I now receive the socket bind event (eSocketBindEvent), and I get the following console output from vTCPStateChange():

Socket 7 -> 0ip:0 State eCLOSED->eTCP_LISTEN

However, the printf() statement “Yield completed.” (as outlined above) is only reached the first time, prior to the “Socket 7 -> …” statement above. After the “Socket 7 -> …” statement, the program seems to hang on portYIELD_WITHIN_API() again:

Attempting yield...
Yield complete.
Socket 7 -> 0ip:0 State eCLOSED->eTCP_LISTEN
Attempting yield...

I’ve tried connecting to the device’s static IP address at port 7 from the attached computer, but no network traffic is shown on Wireshark between the remote computer and device.

It just comes to my mind that the driver has not been well tested when the CPU caching ( DCache ) is enabled.

Could you try to disable it and run the application:

/* Enable ICache and DCache */
// #define CONF_BOARD_ENABLE_CACHE

It is defined in conf_board.h, but make sure you change the right copy.

Thanks PBot for the remark about this line:

-if( ( pxPhyObject->ulLinkStatusMask & phyBMSR_LINK_STATUS ) != 0 )
+if( ( pxPhyObject->ulLinkStatusMask & ( ulBitMask >> 1 ) ) != 0 )

although I think that the shift-right is not correct, and this should do:

-if( ( pxPhyObject->ulLinkStatusMask & phyBMSR_LINK_STATUS ) != 0 )
+if( ( pxPhyObject->ulLinkStatusMask & ulBitMask ) != 0 )

With this change the polling time will be correct, thanks!

Hello @jars121, thanks for reporting this.

I haven’t seen problem with the xEventGroupWaitBits(), or with the FreeRTOS_bind() function.

But: FreeRTOS_bind() shall not be called from the IP-task, and also not from a call-back function like vApplicationIPNetworkEventHook().

If you have enabled configASSERT(), this will be tested in FreeRTOS_bind():

configASSERT( xIsCallingFromIPTask() == pdFALSE );

Would you mind to attach 2 of your configuration files: FreeRTOSConfig.h and FreeRTOSIPConfig.h?

Hello Hein,

i added the right shift because the line
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
would always shift the ulBitMask variable one more time than was actually used inside the loop. For example, if the loop only passed through once with pxPhyObject->xPortCount being 1, the ulBitMask would still be shifted left by 1, resulting in a bitmask of 2 (0010b) after the loop, while the pxPhyObject->ulLinkStatusMask inside the loop would be set to 1 (0001b).
So the check
if( ( pxPhyObject->ulLinkStatusMask & ulBitMask ) != 0 )
would fail.

Thank you for your suggestion to try the project without D-Cache, but i already disabled the CONF_BOARD_ENABLE_CACHE in my conf_board.h. It made no difference if i enabled it or not.

So i tried the suggestion for using caches on https://github.com/jtbr/FreeRTOS-TCP_SAMV71_NetIntf and changed my linker script accordingly (although using 38kb of ram_nocache, as the buffers otherwise wouldn’t fit), while changing the section definitions in gmac_SAM.h from .first_data to .ram_nocache.

Having CONF_BOARD_ENABLE_CACHE in this scenario apparently results in a result conflict with DCache as it runs into an endless loop when trying to invalidate the cache, so i turned CONF_BOARD_ENABLE_CACHE off.
Now it works again, and the buffers can get written, too, but still no packet transfers happen.

It seems,
p_gmac->GMAC_NCR |= GMAC_NCR_TSTART;
does nothing, the data is not sent, but discarded. I can also not see an actual change of the NCR happen, it still stays at 10001100b (RX Enable, TX Enable, Clear Statistics).

EDIT:

Further investigation showed me, that after setting the NCR TSTART bit, TSR is acutally set to 000100010000b (Transmit Frame Corruption Due to AHB Error / HRESP Not OK).

Which led me to this thread: https://www.avrfreaks.net/forum/sam-v71-ethernet-transmit-issue-hresp

As discussed there, i could confirm that the chip actually receives packages, but just can’t send. I could also further confirm, that the changes necessary for the SAM V71b to work have been applied to the instance/gmac.h and component/gmac.h in my ASF (3.48). I’ll try reverting them tomorrow to see if that does the trick. But as it’s 02:24AM at my location now I’ll first catch some sleep.

i added the right shift because the line
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
would always shift the ulBitMask variable one more time than
was actually used inside the loop

Yes, you are right, thanks.

@PBot wrote me (off-list) that his board has a B-release of SAME70.
I looked up the differences and found that the B-release has 6 priority queues for sending packets. These DMA queues must be properly initialised, if not, the transmission won’t work.

After the following change:

 #if( SAME70 != 0 )
 {
     gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_1);
     gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_2);
+    /* Note that SAME70 REV B had 6 priority queues. */
+    gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_3);
+    gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_4);
+    gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_5);
 }
 #endif

the board was able to receive and send network packets.
@PBot tested it with IPERF and a telnet server.

i added this change to the PR on github/freertos.