cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F7 LWIP arp request repeats TX but no RX

nick_berg
Associate II

Hey ,
I have a problem getting LWIP NO_SYS to work on a STM32F765IGT6. We have a custom board with a RMII-PHY and have a 50 MHz clk, data on the RXD0, RXD1 and CSR_DV lines. We also have data on the TXD0, TXD1 and TX-EN lines.

On boot the device transmits an ARP announcement. And when trying to send a test UDP packet the device sends an ARP request, this request is seen and a response given.

nick_berg_0-1698676720222.png

It looks like RX is failing in the device i.e. inside HAL_ETH_ReadData() we never enter:

HAL_StatusTypeDef HAL_ETH_ReadData(ETH_HandleTypeDef *heth, void **pAppBuff)
{
...
/* Check if descriptor is not owned by DMA */
while ((READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_OWN) == (uint32_t)RESET) && (desccnt < desccntmax)
&& (rxdataready == 0U))
{ .... }
...

OWN bit is always set?

This is the output from the SWV Data Console:

SWV ITM Data Console - ITM Port: 0
if: netmask of interface set to 255.255 ?netif: netmask of interface set to 255.255.255.0
netif: GW address of interface set to 131.31.128.1
netif_set_ipaddr: netif address being changed
pbuf_alloced_custom(length=0)
pbuf_alloced_custom(length=0)
pbuf_alloced_custom(length=0)
pbuf_alloced_custom(length=0)
etharp_request: sending ARP request.
pbuf_alloc(length=28)
pbuf_alloc(length=28) == 0x20020464
etharp_raw: sending raw ARP packet.
pbuf_add_header: old 0x20020484 new 0x20020476 (14)
ethernet_output: sending packet 0x20020464
pbuf_free(0x20020464)
pbuf_free: deallocating 0x20020464
netif: added interface st IP addr 131.31.128.18 netmask 255.255.255.0 gw 131.31.128.1
netif: setting default interface st
udp_bind(ipaddr = 0.0.0.0, port = 3000)
udp_bind: bound to 0.0.0.0, port 3000)
pbuf_alloc(length=26)
pbuf_alloc(length=26) == 0x200237f8
udp_send
pbuf_add_header: old 0x20023840 new 0x20023838 (8)
udp_send: added header in given pbuf 0x200237f8
udp_send: sending datagram of length 34
udp_send: UDP packet length 34
udp_send: UDP checksum 0x0000
udp_send: ip_output_if (,,,,0x11,)
pbuf_add_header: old 0x20023838 new 0x20023824 (20)
ip4_output_if: st0
IP header:
+-------------------------------+
| 4 | 5 | 0x00 | 54 | (v, hl, tos, len)
+-------------------------------+
| 0 |000| 0 | (id, flags, offset)
+-------------------------------+
| 255 | 17 | 0x0000 | (ttl, proto, chksum)
+-------------------------------+
| 131 | 31 | 128 | 18 | (src)
+-------------------------------+
| 131 | 31 | 128 | 45 | (dest)
+-------------------------------+
ip4_output_if: call netif->output()
etharp_find_entry: found empty entry 0
etharp_find_entry: selecting empty entry 0
etharp_requt_output: sending packet 0x20020464
pbuf_free(0x20020464)
pbuf_free: deallocating 0x20020464
etharp_query: queued packet 0x200237f8 on ARP entry 0
pbuf_free(0x200237f8)
pbuf_free: 0x200237f8 has ref 1, ending here.
pbuf_alloc(length=26)
pbuf_alloc(length=26) == 0x20023598

I read about the memory/MPU configuration for TX/RX descriptors and the RX buffer. I suspect something is wrong here...

I changed the STM32F765IGTX_FLASH.id file as follows:

/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (xrw) : ORIGIN = 0x20020000, LENGTH = 256k
eth_rx_desc(xrw) : ORIGIN = 0x2007C000, LENGTH = 256 /*0xA0*/
eth_tx_desc(xrw) : ORIGIN = 0x2007C100, LENGTH = 256
eth_rx_pool(xrw) : ORIGIN = 0x2007C200, LENGTH = 15872
}

And at the bottom of the file:

 .ARM.attributes 0 : { *(.ARM.attributes) }
.RxDecripSection (NOLOAD) : { *(.RxDecripSection) } >eth_rx_desc
.TxDecripSection (NOLOAD) : { *(.TxDecripSection) } >eth_tx_desc
.RxArraySection (NOLOAD) : { *(.RxArraySection) } >eth_rx_pool

Tried to force RX_POOL on this memory section with:

__attribute__((section(".RxArraySection"))) extern u8_t memp_memory_RX_POOL_base[];

I can see the memory is used in the Build Analyzer but severely doubt if this is the correct way to do this. Anyway, if I let CubeMX put RX_POOL it in RAM the behavior is the same.

I edited the MPU configuration from an example:

static void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct;

/* Disable the MPU */
HAL_MPU_Disable();

/* Configure the MPU as Strongly ordered for not defined regions */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x00;
MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x87;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Configure the MPU as Normal Non Cacheable for Ethernet Buffers in the SRAM2 */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x2007C000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Configure the MPU as Device for Ethernet Descriptors in the SRAM2 */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x2007C000;
MPU_InitStruct.Size = MPU_REGION_SIZE_512B;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Configure the MPU attributes as WT for SDRAM */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x20020000;
MPU_InitStruct.Size = MPU_REGION_SIZE_256KB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER3;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

/*
Configure the MPU attributes FMC control registers
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0xA0000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_8KB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER4;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x0;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);
*/

/* Enable the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

I'm using a point-to-point connection to my laptop, no switch/router. Any pointers?

1 ACCEPTED SOLUTION

Accepted Solutions
nick_berg
Associate II

Problem turned out to be a loose resistor, on one side. Fully working now 🙂

View solution in original post

3 REPLIES 3
nick_berg
Associate II

While looking at the registers I noticed that the MAC frame counters are not updating.

nick_berg_0-1698850995987.png

nick_berg_1-1698851035650.png

nick_berg_2-1698851050752.png

nick_berg_3-1698851063161.png

nick_berg_4-1698851212040.png

So this is starting to look more like a MAC configuration error to me, not something with the DMA/LWIP.

nick_berg
Associate II

Problem turned out to be a loose resistor, on one side. Fully working now 🙂