No Transmission from GMAC using +TCP on SAME70

tominvert wrote on Wednesday, April 12, 2017:

Hi,

I’m trying to port the provided SAM4E network interface to use with the SAME70, but I’m not getting any data out of the GMAC peripheral. I can see ARP requests being received, processed and responded to, but the packet does not appear on the ethernet bus. The data appears to be correctly formed when xNetworkInterfaceOutput and gmac_dev_write are called. I suspect that the issue is due to the additional prioritiy queues introduced with the SAME70 that weren’t present on the SAM4E, but I’m a novice at both low-level ethernet communications and DMA data transfer so I’m not sure where to look for issues. I can provide my full NetworkInterface.c and modfied gmac.c files if it helps - I can’t see how to attach files here though. I’ve posted my initialisation functions and send functions below. My functions don’t include any Phy initialisation or communications as our MCU connects directly to an ethernet switch over RMII. I’m running FreeRTOS V9.0.0, compiling in Atmel Studio with GCC.

Any help is greatly appreciated. Cheers.

static BaseType_t prvGMACInit( void )
{
	/* Wait for PHY to be ready (CAT811: Max400ms). */
	volatile uint32_t ul_delay = sysclk_get_cpu_hz() / 1000 / 3 * 400;
	while (ul_delay--) {
	}
		
	uint32_t ncfgr;
	gmac_options_t gmac_option;

	pmc_enable_periph_clk(ID_GMAC);

	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 );
	gmac_set_mdc_clock(GMAC, sysclk_get_peripheral_hz());
	gmac_set_speed(GMAC, true);
	gmac_enable_full_duplex(GMAC, true);
	gmac_select_mii_mode(GMAC, GMAC_PHY_RMII);

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

	/* The GMAC driver will call a hook prvRxCallback(), which
	in turn will wake-up the task by calling vTaskNotifyGiveFromISR() */
	gmac_dev_set_rx_callback( &gs_gmac_dev, GMAC_QUE_0, prvRxCallback );
	gmac_set_address( GMAC, 1, (uint8_t*)llmnr_mac_address );

	ncfgr = GMAC_NCFGR_SPD | GMAC_NCFGR_FD;

	GMAC->GMAC_NCFGR = ( GMAC->GMAC_NCFGR & ~( GMAC_NCFGR_SPD | GMAC_NCFGR_FD ) ) | ncfgr;
	
	// Set Link Up
	bInterfaceUp = true;
	ioport_set_pin_level(PIN_LED_LINK, true);

	return 1;
}

BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
{
	if( bInterfaceUp )
	{
		/* Not interested in a call-back after TX. */
		iptraceNETWORK_INTERFACE_TRANSMIT();
		printf("debug: outgoing packet length = %lu bytes\r\n", pxDescriptor->xDataLength);
		gmac_dev_write( &gs_gmac_dev, GMAC_QUE_0, (void *)pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength, NULL );
	}

	if( bReleaseAfterSend != pdFALSE )
	{
		vReleaseNetworkBufferAndDescriptor( pxDescriptor );
	}
	return pdTRUE;
}
static void gmac_reset_tx_mem(gmac_device_t* p_dev, gmac_quelist_t queue_idx)
{
	Gmac *p_hw = p_dev->p_hw;
	uint8_t *p_tx_buff = p_dev->gmac_queue_list[queue_idx].p_tx_buffer;
	gmac_tx_descriptor_t *p_td = p_dev->gmac_queue_list[queue_idx].p_tx_dscr;

	uint32_t ul_index;
	uint32_t ul_address;

	/* Disable TX */
	gmac_enable_transmit(p_hw, 0);

	/* Set up the TX descriptors */
	CIRC_CLEAR(p_dev->gmac_queue_list[queue_idx].us_tx_head, p_dev->gmac_queue_list[queue_idx].us_tx_tail);
	for (ul_index = 0; ul_index < p_dev->gmac_queue_list[queue_idx].us_tx_list_size; ul_index++) 
	{
		ul_address = (uint32_t) (&(p_tx_buff[ul_index * GMAC_TX_UNITSIZE]));
		p_td[ul_index].addr = ul_address;
		p_td[ul_index].status.val = GMAC_TXD_USED;
	}
	p_td[p_dev->gmac_queue_list[queue_idx].us_tx_list_size - 1].status.val =
	GMAC_TXD_USED | GMAC_TXD_WRAP;

	/* Set transmit buffer queue */
	if(queue_idx == GMAC_QUE_0) gmac_set_tx_queue(p_hw, (uint32_t) p_td);
	else						gmac_set_tx_priority_queue(p_hw, (uint32_t) p_td, queue_idx);
}

/**
 * \brief Disable receiver, reset registers and descriptor list.
 *
 * \param p_drv Pointer to GMAC Driver instance.
 */
static void gmac_reset_rx_mem(gmac_device_t* p_dev, gmac_quelist_t queue_idx)
{
	Gmac *p_hw = p_dev->p_hw;
	uint8_t *p_rx_buff = p_dev->gmac_queue_list[queue_idx].p_rx_buffer;
	gmac_rx_descriptor_t *pRd = p_dev->gmac_queue_list[queue_idx].p_rx_dscr;

	uint32_t ul_index;
	uint32_t ul_address;

	/* Disable RX */
	gmac_enable_receive(p_hw, 0);

	/* Set up the RX descriptors */
	p_dev->gmac_queue_list[queue_idx].us_rx_idx = 0;
	for (ul_index = 0; ul_index < p_dev->gmac_queue_list[queue_idx].us_rx_list_size; ul_index++) {
		ul_address = (uint32_t) (&(p_rx_buff[ul_index * GMAC_RX_UNITSIZE]));
		pRd[ul_index].addr.val = ul_address & GMAC_RXD_ADDR_MASK;
		pRd[ul_index].status.val = 0;
	}
	pRd[p_dev->gmac_queue_list[queue_idx].us_rx_list_size - 1].addr.val |= GMAC_RXD_WRAP;

	/* Set receive buffer queue */
	if(queue_idx == GMAC_QUE_0) {
		gmac_set_rx_queue(p_hw, (uint32_t) pRd);
		} else {
		gmac_set_rx_priority_queue(p_hw, (uint32_t) pRd, queue_idx);
	}
}

/**
 * \brief Initialize the allocated buffer lists for GMAC driver to transfer data.
 * Must be invoked after gmac_dev_init() but before RX/TX starts.
 *
 * \note If input address is not 8-byte aligned, the address is automatically
 *       adjusted and the list size is reduced by one.
 *
 * \param p_gmac Pointer to GMAC instance.
 * \param p_gmac_dev Pointer to GMAC device instance.
 * \param p_dev_mm Pointer to the GMAC memory management control block.
 * \param p_tx_cb Pointer to allocated TX callback list.
 *
 * \return GMAC_OK or GMAC_PARAM.
 */
static uint8_t gmac_init_mem(gmac_device_t* p_gmac_dev, gmac_quelist_t queue_idx, gmac_dev_mem_t* p_dev_mm, gmac_dev_tx_cb_t* p_tx_cb)
{
	if (p_dev_mm->us_rx_size <= 1 || p_dev_mm->us_tx_size <= 1 || p_tx_cb == NULL) 	return GMAC_PARAM;

	gmac_queue_t* p_gmac_queue = &p_gmac_dev->gmac_queue_list[queue_idx];

	/* Assign RX buffers */
	if (((uint32_t) p_dev_mm->p_rx_buffer & 0x7) || ((uint32_t) p_dev_mm->p_rx_dscr & 0x7)) p_dev_mm->us_rx_size--;
	
	p_gmac_queue->p_rx_buffer = (uint8_t *) ((uint32_t) p_dev_mm->p_rx_buffer & 0xFFFFFFF8);
	p_gmac_queue->p_rx_dscr =	(gmac_rx_descriptor_t *) ((uint32_t) p_dev_mm->p_rx_dscr & 0xFFFFFFF8);
	p_gmac_queue->us_rx_list_size = p_dev_mm->us_rx_size;

	/* Assign TX buffers */
	if (((uint32_t) p_dev_mm->p_tx_buffer & 0x7) || ((uint32_t) p_dev_mm->p_tx_dscr & 0x7)) p_dev_mm->us_tx_size--;
	
	p_gmac_queue->p_tx_buffer = (uint8_t *) ((uint32_t) p_dev_mm->p_tx_buffer & 0xFFFFFFF8);
	p_gmac_queue->p_tx_dscr = (gmac_tx_descriptor_t *) ((uint32_t) p_dev_mm->p_tx_dscr & 0xFFFFFFF8);
	p_gmac_queue->us_tx_list_size = p_dev_mm->us_tx_size;
	p_gmac_queue->func_tx_cb_list = p_tx_cb;

	/* Reset TX & RX */
	gmac_reset_rx_mem(p_gmac_dev, queue_idx);
	gmac_reset_tx_mem(p_gmac_dev, queue_idx);

	return GMAC_OK;
}

static void gmac_init_queue(Gmac* p_gmac, gmac_device_t* p_gmac_dev)
{
	gmac_dev_mem_t gmac_dev_mm;

	/* Clear interrupts */
	gmac_get_priority_interrupt_status(p_gmac, GMAC_QUE_2);
	gmac_get_priority_interrupt_status(p_gmac, GMAC_QUE_1);

	gmac_set_tx_priority_queue(p_gmac, (uint32_t)&gs_tx_desc_null, GMAC_QUE_2);
	gmac_set_tx_priority_queue(p_gmac, (uint32_t)&gs_tx_desc_null, GMAC_QUE_1);
	gmac_set_rx_priority_queue(p_gmac, (uint32_t)&gs_rx_desc_null, GMAC_QUE_2);
	gmac_set_rx_priority_queue(p_gmac, (uint32_t)&gs_rx_desc_null, GMAC_QUE_1);

	/* Clear interrupts */
	gmac_get_interrupt_status(p_gmac);

	/* Fill in GMAC device memory management */
	gmac_dev_mm.p_rx_buffer = gs_uc_rx_buffer;
	gmac_dev_mm.p_rx_dscr = gs_rx_desc;
	gmac_dev_mm.us_rx_size = GMAC_RX_BUFFERS;

	gmac_dev_mm.p_tx_buffer = gs_uc_tx_buffer;
	gmac_dev_mm.p_tx_dscr = gs_tx_desc;
	gmac_dev_mm.us_tx_size = GMAC_TX_BUFFERS;

	gmac_init_mem(p_gmac_dev, GMAC_QUE_0, &gmac_dev_mm, gs_tx_callback);

	/* Enable Rx and Tx, plus the statistics register */
	gmac_enable_transmit(p_gmac, true);
	gmac_enable_receive(p_gmac, true);
	gmac_enable_statistics_write(p_gmac, true);

	/* Set up the interrupts for transmission and errors */
	gmac_enable_interrupt(p_gmac,
	GMAC_IER_RLEX  | /* Enable retry limit exceeded interrupt. */
	GMAC_IER_RCOMP | /* Enable receive complete interrupt. */
	GMAC_IER_RXUBR | /* Enable receive used bit read interrupt. */
	GMAC_IER_ROVR  | /* Enable receive overrun interrupt. */
	GMAC_IER_TCOMP | /* Enable transmit complete interrupt. */
	GMAC_IER_TUR   | /* Enable transmit underrun interrupt. */
	GMAC_IER_TFC   | /* Enable transmit buffers exhausted in mid-frame interrupt. */
	GMAC_IER_HRESP | /* Enable Hresp not OK interrupt. */
	GMAC_IER_PFNZ  | /* Enable pause frame received interrupt. */
	GMAC_IER_PTZ);   /* Enable pause time zero interrupt. */
}

/**
 * \brief Initialize the GMAC driver.
 *
 * \param p_gmac   Pointer to the GMAC instance.
 * \param p_gmac_dev Pointer to the GMAC device instance.
 * \param p_opt GMAC configure options.
 */
void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,	gmac_options_t* p_opt)
{
	gmac_dev_mem_t gmac_dev_mm;

	/* Disable TX & RX and more */
	gmac_network_control(p_gmac, 0);
	gmac_disable_interrupt(p_gmac, ~0u);
	gmac_clear_statistics(p_gmac);

	/* Clear all status bits in the receive status register. */
	gmac_clear_rx_status(p_gmac, GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA);

	/* Clear all status bits in the transmit status register */
	gmac_clear_tx_status(p_gmac, GMAC_TSR_UBR | GMAC_TSR_COL | GMAC_TSR_RLE
			| GMAC_TSR_TXGO | GMAC_TSR_TFC | GMAC_TSR_TXCOMP | GMAC_TSR_HRESP);

	/* Clear interrupts */
	gmac_get_interrupt_status(p_gmac);
	
#if !defined(ETHERNET_CONF_DATA_OFFSET)
	/*  Receive Buffer Offset
	 * Indicates the number of bytes by which the received data
	 * is offset from the start of the receive buffer
	 * which can be handy for alignment reasons */
	/* Note: FreeRTOS+TCP wants to have this offset set to 2 bytes */
	#error ETHERNET_CONF_DATA_OFFSET not defined, assuming 0
#endif
	/* Enable the copy of data into the buffers
	   ignore broadcasts, and not copy FCS. */
	gmac_set_config(p_gmac,
		( gmac_get_config(p_gmac) & ~GMAC_NCFGR_RXBUFO_Msk ) |
		GMAC_NCFGR_RFCS |   /*  Remove FCS, frame check sequence (last 4 bytes) */
		GMAC_NCFGR_PEN |    /* Pause Enable */
		GMAC_NCFGR_RXBUFO( ETHERNET_CONF_DATA_OFFSET ) |
		GMAC_RXD_RXCOEN );

	/*
	 * GMAC_DCFGR_TXCOEN: (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable.
	 * Note: the SAM4E does have RX checksum offloading
	 * but TX checksum offloading has NOT been implemented.
	 */
	p_gmac->GMAC_DCFGR |= GMAC_DCFGR_TXCOEN;

	gmac_enable_copy_all(p_gmac, p_opt->uc_copy_all_frame);
	gmac_disable_broadcast(p_gmac, p_opt->uc_no_boardcast);

	/* Fill in GMAC device memory management */
	gmac_dev_mm.p_rx_buffer = gs_uc_rx_buffer;
	gmac_dev_mm.p_rx_dscr = gs_rx_desc;
	gmac_dev_mm.us_rx_size = GMAC_RX_BUFFERS;

	gmac_dev_mm.p_tx_buffer = gs_uc_tx_buffer;
	gmac_dev_mm.p_tx_dscr = gs_tx_desc;
	gmac_dev_mm.us_tx_size = GMAC_TX_BUFFERS;

	gmac_init_queue(p_gmac, p_gmac_dev);
	gmac_set_address(p_gmac, 0, p_opt->uc_mac_addr);
}

/**
 * \brief Send ulLength bytes from pcFrom. This copies the buffer to one of the
 * GMAC Tx buffers, and then indicates to the GMAC that the buffer is ready.
 * If lEndOfFrame is true then the data being copied is the end of the frame
 * and the frame can be transmitted.
 *
 * \param p_gmac_dev Pointer to the GMAC device instance.
 * \param p_buffer       Pointer to the data buffer.
 * \param ul_size    Length of the frame.
 * \param func_tx_cb  Transmit callback function.
 *
 * \return Length sent.
 */
uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, gmac_quelist_t queue_idx, void *p_buffer, uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb)
{
	volatile gmac_tx_descriptor_t *p_tx_td;
	volatile gmac_dev_tx_cb_t *p_func_tx_cb;
	Gmac *p_hw = p_gmac_dev->p_hw;
	gmac_queue_t* p_gmac_queue = &p_gmac_dev->gmac_queue_list[queue_idx];

	/* Check parameter */
	if (ul_size > GMAC_TX_UNITSIZE) return GMAC_PARAM;

	/* Pointers to the current transmit descriptor */
	p_tx_td = &p_gmac_queue->p_tx_dscr[p_gmac_queue->us_tx_head];

	/* If no free TxTd, buffer can't be sent, schedule the wakeup callback */
	if (CIRC_SPACE(p_gmac_queue->us_tx_head, p_gmac_queue->us_tx_tail, p_gmac_queue->us_tx_list_size) == 0)
	{
		if ((p_tx_td->status.val & GMAC_TXD_USED) == 0)	return GMAC_TX_BUSY;
	}
	
	/* Pointers to the current Tx callback */
	p_func_tx_cb = &p_gmac_queue->func_tx_cb_list[p_gmac_queue->us_tx_head];

	/* Set up/copy data to transmission buffer */
	if (p_buffer && ul_size) 
	{
		/* Driver manages the ring buffer */
		/* Calculating the checksum here is faster than calculating it from the GMAC buffer
		 * because withing p_buffer, it is well aligned */
		memcpy((void *)p_tx_td->addr, p_buffer, ul_size);
// 		vGMACGenerateChecksum( ( uint8_t * ) p_tx_td->addr );	// Done in Hardware on SAME70
	}

	/* Tx callback */
	*p_func_tx_cb = func_tx_cb;

	/* Update transmit descriptor status */

	/* The buffer size defined is the length of ethernet frame,
	   so it's always the last buffer of the frame. */
	if( p_gmac_queue->us_tx_head == ( int32_t )( p_gmac_queue->us_tx_list_size - 1 ) )
	{
		/* No need to 'and' with GMAC_TXD_LEN_MASK because ul_size has been checked */
		p_tx_td->status.val = ul_size | GMAC_TXD_LAST | GMAC_TXD_WRAP;
	} 
	else 
	{
		p_tx_td->status.val = ul_size | GMAC_TXD_LAST;
	}

	circ_inc32( &p_gmac_queue->us_tx_head, p_gmac_queue->us_tx_list_size );

	/* Now start to transmit if it is still not done */
	gmac_start_transmission(p_hw);

	return GMAC_OK;
}

tominvert wrote on Wednesday, April 12, 2017:

Also I have managed to run a TCP server using lwIP with the same hardware, so I’m confident that its a software driver issue. The reason I’m switching to +TCP is that I’ve struggled to get the lwIP server to function reliably under moderate load. My application already uses FreeRTOS, and +TCP seemed to be documented far better than lwIP, so I decided it was worth the effort to try it.

heinbali01 wrote on Wednesday, April 12, 2017:

Hi Tom, unfortunately I do not have a comparable hardware platform to test it (only SAM4E). But later today I will have a look at your sources. We’ll find the problem :slight_smile:

heinbali01 wrote on Wednesday, April 12, 2017:

I can’t see how to attach files here though

While typing, you see “Add attachments” below your message?

Press it, and press Browse, and you can select you file. Could you zip both your NetworkInterface.c and gmac file?

heinbali01 wrote on Wednesday, April 12, 2017:

I don’t include any PHY initialisation or communications as our
MCU connects directly to an Ethernet switch over RMII

You do receive ARP messages, so the PHY seems to work. But don’t you want to actively start an auto-negotiation after the Link Status goes high? And don’t you want to advertise some properties ( duplex / dmix / speed )?

If the packet to be sent is too small, it might not get sent data at all.

The EMAC has a minimum length it can transmit.

For a STM32F4, we’ve defined:

#define ipconfigETHERNET_MINIMUM_PACKET_BYTES    60

Shorter packets, like ARP responses, may get extended with zero’s.
Put the above define into your FreeRTOSIPConfig.h.
Regards.

tominvert wrote on Thursday, April 13, 2017:

I found the issue - amateur mistake, forgot to include the pin multiplexer configuration, as lwIP had included it in the GMAC init function but the equivalent +TCP function left it to be configured elsewhere (board_init in the example). I’m quite surprised I had anything work at all. Thanks for the assistance.

heinbali01 wrote on Thursday, April 13, 2017:

Very good Tom, and thanks for reporting back.
Pin multiplexers can be confusing.
Still you might want to define ipconfigETHERNET_MINIMUM_PACKET_BYTES = 60, because Ethernet doesn’t like smaller packets. The 60 bytes is excluding the 4-byte (“hardware”) CRC that will be added by the PHY.

rtimenoob wrote on Thursday, April 13, 2017:

I am also trying to get to run my SAME70 together with freertos and lwip. Could u please tell me your freertos settings in conf_tasks.h?
Although in the datasheet it is said, that the BASPRI register is using bits [7:4] (4 BITS), in the CMSIS configPRIO_BITS is defined with 3. I am not sure if 3 or 4 Bits are correct. Of course all other priority settings depend on it.
Do u know if it is possible to run a WEB Server with SSI and CGI on freertos+TCP? On an older project I was able to get to run freertos + lwip but the throughput was very poor. I put a lot of time in optimization the lwip stack (user pools, NO_COPY…) but I had unpredictable crashes :frowning:
I have a new try now on the SAME70.
I am looking forward to your answer.
Thank u very much.

heinbali01 wrote on Thursday, April 13, 2017:

Hi Werner,

Do u know if it is possible to run a WEB Server with SSI and CGI on freertos+TCP?

FreeRTOS+TCP does have a web-server that is simple and fast. It needs a kind of stdio interface to a medium. You can use FreeRTOS+FAT for this, on a RAM-disk or an SD-card.

    FreeRTOS-Plus-TCP/protocols/HTTP/FreeRTOS_HTTP_server.c

It does not support SSI and CGI explicitly, what it has is an Application Hook:

    size_t uxApplicationHTTPHandleRequestHook( const char *pcURLData, char *pcBuffer, size_t uxBufferLength )

It is called for every GET request received. It provides you the URL and a buffer in which the response can be formatted.

    #define ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK      1
    #define ipconfigHTTP_REQUEST_CHARACTER		      '?'

In the above example, all URL’s containing a question mark will be forwarded to the application.
In case your application does not want to handle a request, just return 0.

How I used it: many GET request need to retrieve a file. That is all handled by the webserver directly.
The JS or JQuery code can do a special GET (using ‘jQuery.ajax’), to asks or tell things to your application, as for example:

    /question?temperature=?
    /question?volume=12
    /question?remote_access=*&settings={"pass":"OJ8T5n4o%U$No4iun","name":"John"}

Please have a try with +TCP on your SAME7.

Currently, the Atmel drivers are not yet zero-copy. The functions gmac_dev_read() and gmac_dev_write() must be adapted to make them zero-copy. If you want I can assist with that.
In this ZIP file you find an example of a zero-copy +TCP driver ( for STM32F4x )

heinbali01 wrote on Thursday, April 20, 2017:

I wrote:

Currently, the Atmel drivers are not yet zero-copy

I just checked the +TCP SAM4E driver:

It is impossible to make the RX-path zero-copy. The EMAC uses fixed-size (128-byte) buffers for reception.

It is possible to make transmission zero-copy: the gmac driver has some application-hook GMAC_USES_TX_CALLBACK. But, the call-back from the driver to the application is being done from within the ETH interrupt. That is against the idea of a deferred interrupt handler: let the ISR wake-up a task (prvEMACHandlerTask), and let the task check the DMA descriptors.
Also, the ISR gmac_handler() will become quite long when GMAC_USES_TX_CALLBACK is enabled. I would consider rewriting the interrupt handler.

febe2 wrote on Thursday, September 14, 2017:

Hi Guys,
My latest project idea was to transfer a file via ftp server to my microcontroller and save this file on my sd card plugged in to my sam e70 eva board.

On my next step I found a project for the sam4 board (http://www.freertos.org/FreeRTOS…) and I wanted to realzie it on my sam e70 board.

I downloaded an example file from http://www.freertos.org/FreeRTOS… (freerrtos-Plus/Demo/FreeRTOS_Plus_TCP_and_FAT_ATSAM4E/RtosDemo.atsln) and compiled it successfully in atmel studio for sam4e.

Next step would be to port the project from sam4e to sam e70.

What exactly do i have to port? only the network interface?

toastedcpu wrote on Friday, September 15, 2017:

Hello,
I am working on the SAM E70 explained board. I did not get it to work yet.

My approach is to use in Atemel Studio 7 File->New Example project, create a FreeRTOS demo project, create a LWIP demo project and copy the folders from LWIP into FreeRTOS. I managed to run both demos seperately. Perhaps to copy FreeRTOS into LWIP will envolve less work because of Ethernet peripherals will already be fine.

I had to delete the test subfolder of lwip because of compilation problems. I added in the project Proerties Toolchain->ARM/GNU C compiler Directories all the lwip directories of the lwip demo. I dot fully invegate the mismatch of conf_clock.where in one I have #define CONFIG_SYSCLOCK_RES set to SYSCLOCK_PRES_1, while the other is SYSCLOCK_PRES_2.
Frank

rtel wrote on Friday, September 15, 2017:

lwIP will require a different configuration to use in a multi-threaded
environment.

I’m afraid I can’t answer device specific questions - we use a LOT of
different chips and you would be able to find device specific answers
faster than us as we would have to start by getting the hardware manual.

We have our own TCP/IP stack running on a SAM4E if that is useful as a
reference, or to adapt:
http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCPIP_FAT_Examples_Atmel_SAM4E.html

svlas wrote on Wednesday, February 07, 2018:

Hi Tom,
Can you send your full networkinterface.c

svlas wrote on Wednesday, February 07, 2018:

Hi Tom,
Please send your full networkinterface.c

heinbali01 wrote on Wednesday, February 07, 2018:

Hi Serhii, please find attached the latest combined STM32F4 /F7 driver.
Do not hesitate to ask questions here if you encounter any problem.
Thanks,

heinbali01 wrote on Wednesday, February 07, 2018:

I’m just reading back the title of this old thread and see that it’s about an Atmel part, not an ST part.
Please find attached a combined driver for both SAM4E and SAME70.

This driver is partly zero-copy:

#define ipconfigZERO_COPY_TX_DRIVER   1
#define ipconfigZERO_COPY_RX_DRIVER   0

The DMA reception-buffers in the Atmel parts have a fixed length of 128 byte. A single buffer can rarely hold a complete Ethernet packet.

Do not hesitate to complain :slight_smile:

svlas wrote on Wednesday, February 07, 2018:

Hi Hein,
Thanks for your response. I’ll try to add this to my project

heinbali01 wrote on Wednesday, February 07, 2018:

The driver also contains a generic PHY-driver for FreeRTOS+TCP :

    common/phyHandling.c
    include/phyHandling.h

I hope that your PHY is also supported by this driver.
The first thing to do will be to check if your PHY is recognised and know.

rhornecker wrote on Wednesday, February 07, 2018:

Hi Hein,

when I include your driver into my project I get a ‘HRESP not ok’ error on the GMAC_ISR and GMAC_RSR register. I am aware that I have to include a dummy Tx descripter, that however did not fix the issue.

Ralph