I’ve created a task that implements a TCP echo server.
I have a TCP client that sends a string to the TCP echo server written in Python, which I know it’s working with a LwIP TCP echo server.
The Nucleo-144 is programmed with an IP address of 192.168.0.10 (mac address 0x00, 0x11, 0x22, 0x33, 0x44, 0x55) and the Windows machine is 192.168.0.100.
I’m using port 80.
I can see with wireShark that the ARP is sent:
11 61.282383 Dell_43:e4:58 Broadcast ARP 42 Who has 192.168.0.10? Tell 192.168.0.100
But no answer is coming back.
Any ideas on how to find out what is going on?
It’s the ETH peripheral with ETH_Handler as default ISR.
If using stm32f4xx_hal_eth.c you can step into the init code HAL_ETH_Init to see what’s going on.
HAL_Eth_Init() returns HAL_OK.
xNetworkInterfaceInitialise() return pdFAIL but it seems normal…
/* For now pdFAIL will be returned. But prvEMACHandlerTask() is running
* and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */
xResult = pdFAIL;
The prvEMACHandlerTask is running but this if never comes true.
if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )
{
/* Something has changed to a Link Status, need re-check. */
prvEthernetUpdateConfig( pdFALSE );
}
The MAC address has reported by FreeRTOS_GetMACAddress() in xNetworkInterfaceInitialise is
00:11:22:33:44:55 which is the one presented to FreeRTOS_IPInit().
What is “the strapped PHY address” ?
Is there any other MAC address defined? Is there any unique ID IC on Nucleo-144?
You should be able to step through your ethernet interface initialization in HAL_ETH_Init which among other things should program the provided MAC address into the ETH hardware.
Also when in doubt check that the PHY is found at it’s fixed address (boot-strapped by external resistors) and verify that the PHY then detects ethernet link up with the expected mode and speed (e.g. 100MBit full-duplex). Watch the LEDs on your RJ45 plug and/or check the link state on the peer PC/machine.
Finally link-up is signaled to the network stack and the real fun starts
HAL_ETH_Init return HAL_OK.
xNetworkInterfaceInitialise() return pdFAIL but it seems normal…
/* For now pdFAIL will be returned. But prvEMACHandlerTask() is running
* and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */
xResult = pdFAIL;
The prvEMACHandlerTask is running but this if never comes true.
if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )
{
/* Something has changed to a Link Status, need re-check. */
prvEthernetUpdateConfig( pdFALSE );
}
Both leds in the RJ45 connector are on.
I think the thing missing here in that the link never goes up!
What would be the reason for that?
If both LEDs are ON than the the PHY has detected a 100 MBit-FD link-up. Then step through xPhyCheckLinkStatus and/or check the returned pxPhyObject members like ulLinkStatusMask as defined in phyHandling.h (I guess) to verify that it’s reported properly and prvEthernetUpdateConfig gets invoked.
It will automatically detect on what addresses ( 0 … 31 ) a PHY chip is found. It recognises most types of PHY’s.
It works with a simple configuration: either auto-nego, or using a manual set-up. 99% of the projects will use the auto-negotiation and go for the maximum speed, auto-DMX, and full duplex.
xPhyCheckLinkStatus keeps being called, but it seems to return pdFALSE.
Also strangely so does xNetworkInterfaceInitialise().
in xPhyCheckLinkStatus()
if( xHadReception > 0 ) is always false
the else if is true
the for loop however does not seem to run since pxPhyObject->xPortCount is 0.
and the final outcome is:
else
{
/* The link status is low, polling may be done more frequently. */
pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_LOW_CHECK_TIME_MS );
}
I don’t think pxPhyObject->xPortCount should be 0, since the assignment of pxPhyObject->ulLinkStatusMask happens inside the for loop…
Why is pxPhyObject->xPortCount equal to 0?
In xPhyDiscover() phyHandling.c the if
/* A valid PHY id can not be all zeros or all ones. */
if( ( ulLowerID != ( uint16_t ) ~0U ) && ( ulLowerID != ( uint16_t ) 0U ) )
Have you stepped through xPhyDiscover() already?
As you probably know, switching off compiler optimisation makes stepping a lot easier.
Does the fnPhyRead() function return any other number than all ones (0xffff)?
Is your implementation of HAL_ETH_MspInit() correct? It defines clocks and the direction and function of GPIO pins involved.
I am attaching a version that I use for tests with an STM32F7x: HAL_ETH_MspInit.c (2.0 KB)
It is just an example, your hardware might be different from my STM32F746 Discovery board.
fnPhyRead always returns ulLowerID with 0! I’ve checked the 32 returns.
It’s RMII wired.
My HAL_ETH_MspInit() seems to be much simpler than yours
__weak void HAL_ETH_MspInit( ETH_HandleTypeDef * heth )
{
/* NOTE : This function Should not be modified, when the callback is needed,
* the HAL_ETH_MspInit could be implemented in the user file
*/
( void ) heth;
}
But I have copied the files from:
FreeRTOSv202012.00\FreeRTOS-Plus\Source\FreeRTOS-Plus-TCP\portable\NetworkInterface\STM32Fxx
This seems to be the problem.
Where should I get the correct file?
They are dated 15/12/2020
The HAL_ETH_MspInit() function is not part of the FreeRTOS distribution, because each board may be different.
Have you looked up the schemes of a Nucleo-144, regarding the ETH and PHY? Try to get a list of all pins involved and compose a HAL_ETH_MspInit().
Or, alternatively, try to find an Ethernet project for Nucleo-144, which may also be a lwIP project. The pinnings are the same.
It is good to use the following github locations to find the latests drivers: