FreeRTOS +TCP on SAME70

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.

Good Find! I have worked with the rev. B chips before and never could get them working, glad to see someone figured it out. I’m new to the thread, but I did find an example of rtos+tcp long ago on a forum. I noticed the link has since been broken and uploaded a copy to git:


It works on the ATSAME70-XPLD board, and uses RTOS 10.0.

Perhaps it may be useful,

I just received the following question about the SAME70 network driver:

have you been able (or tried) to use the +TCP implementation
with DCache enabled? I’m trying to use a UART DMA process
which relies on DCache, so it looks like I’ll need to get DCache
functioning with the +TCP stack.

Answer: both should be possible, with and without DCache.samE70_flash.ld.zip (2.0 KB)

I am attaching my “samE70_flash.ld”, which defines :

.first_data (NOLOAD) :
{
    . = ALIGN(4);
    _first_data = . ;
    *(._first_data ._first_data.*)
    . = ALIGN(4);
    _e_first_data = . ;
} > ram

at the very beginning of RAM. If I am not mistaken, that part of RAM has no caching.

So this should make it possible to enable data cache, while the +TCP driver still works.
Please verify if the beginning of RAM is really not cached.

A driver like Zynq also works well with cached memory: each time when memory is handed over from peripheral to host Xil_DCacheInvalidateRange() will be called.
When the host hands over RAM to the peripheral, Xil_DCacheFlushRange() will be called.

It is important that each object ( DMA descriptors and packet buffers ) has a length that is a multiple of a cache page, often 32 bytes:

__attribute__ ( ( aligned( 32 ) ) )   // align with DCache pages
__attribute__ ( ( section( ".first_data" ) ) )   // Allocate in the beginning of RAM
    uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * NETWORK_BUFFER_SIZE ];

FWIW, we have been using SAME70Q20B with KNZ8081 phy and cache enabled for over a year. We define a non-cached area of memory in the MMU and allocate the DMA buffers in that. A complication is that the standard newlib supplied for ARM M7 chips is compiled with unaligned memory accesses enabled, but they are not allowed when the memory is set to non-cached, and memcpy in particular does unaligned accesses.

David, thanks for these insights. That may help others who are on the same path.

with KNZ8081 phy

That should be KSZ8081, I suppose?

A complication is that the standard newlib supplied for ARM
M7 chips is compiled with unaligned memory accesses enabled

As you have seen, the +TCP driver only does aligned access to memory that is shared with DMA.
Do you think that this may cause other potential problems?

Thanks again to Hein for the ongoing support with the SAME70. I’ve continued my efforts to get DCache() working with +TCP, but haven’t had any success thus far. Per Hein’s earlier post, I declare a non-cached region of memory in my linker script as follows:

/* Memory Spaces Definitions */
MEMORY
{
  rom (rx)     : ORIGIN = 0x00400000, LENGTH = 0x00200000
  ram (wrx)    : ORIGIN = 0x20400000, LENGTH = 0x00056800
  ram_nocache (rwx) : ORIGIN = 0x20456800, LENGTH = 0x9800
}

...

/* ethernet */
.ram_nocache (NOLOAD):
{
    . = ALIGN(4);
    _sram_nocache = .;
} > ram_nocache

An obvious difference between my current approach and Hein’s listed above, is that my non-cached memory allocation is at the end of the memory region, after the heap allocation, whereas Hein’s is at the start. Could this be causing me issues?

With the above memory definition in place, I construct the various network buffers in gmac_SAM.c with the (seemingly) correct memory allocation (showing 2 below as illustration) :

COMPILER_ALIGNED(8)
__attribute__ ((section(".ram_nocache"))) uint8_t ucNetworkPackets[ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * NETWORK_BUFFER_SIZE];

COMPILER_ALIGNED(8)
__attribute__ ((section(".ram_nocache"))) static gmac_tx_descriptor_t gs_tx_desc[GMAC_TX_BUFFERS];

@dc42 I don’t suppose the above is similar to how you’ve got cache enabled and working with your SAME70?