Skip to content

Conversation

maribu
Copy link
Member

@maribu maribu commented Oct 9, 2020

Contribution description

Most Ethernet PHYs support auto-negotiation of signaling specification. This is more reliable and easier to use than manual configuration, as this will select the fastest configuration supported by both communication partners automatically.

This PR exposes the auto-negotiation capability via the (pseudo-) module stm32_eth_auto. Note: It requires that the Ethernet PHY is actually capable of this - but I don't think any Fast Ethernet PHYs without auto-negotiation are on the market anymore.

This PR also fixes the link state notification, why previously only covered link up events and stopped worked after the first event was generated. With this fix, the link state will be continuously monitored (sadly by polling every second the state) and both link up and link down event should be generated.

Testing procedure

  • The Ethernet of the STM32s should still work
  • With USEMODULE += stm32_eth_link_up, both link up and link down event should be generated. This should now work after the first plugging in.
  • With USEMODULE += stm32_eth_auto, the Ethernet device should use the highest speed supported by both partners, regardless of manual configuration
    • Check this by e.g. setting manual speed to 10 Mbps and half duplex. When connected to another Ethernet device capable of 100 Mbps and full-duplex, the driver should pick this over the 10 Mbps and half duplex settings
  • This should fix cpu/stm32/eth, board/nucleo-f767z1: ethernet initialisation fails sometimes #13490 even without stm32_eth_auto being used by simply waiting for the PHY to power up before trying to configure it.

Issues/PRs references

Depends on and includes:

Fixes: #13490

@maribu maribu added Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation Area: cpu Area: CPU/MCU ports labels Oct 9, 2020
@maribu maribu added State: waiting for other PR State: The PR requires another PR to be merged first State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet labels Oct 9, 2020
@maribu
Copy link
Member Author

maribu commented Oct 10, 2020

I think it makes sense to keep manual PHY configuration and implement this as optional (pseudo) module. That way users with low ROM could opt out (by not explicitly opting in). I would like to have the optional auto-negotiation depend on the stm32_eth_link_up module. That would allow for:

  1. Re-negotiate the link parameters when the link is changed
    • E.g. when disconnecting the cable from an 100 Mbps communication partner and connecting it to an only 10 Mbps partner, currently the link would stay at 100 Mbps and connection would fail
  2. Perform the link setup async. Right now the initialization takes half a second or so due to the slow auto-negotiation. Delaying boot (when auto-initialization the Ethernet device) by half a bloody second seems to be a poor idea.

@maribu maribu force-pushed the stm32-eth-negotiate branch from 2dfacf4 to 98ba1bf Compare October 12, 2020 09:01
@maribu maribu removed the State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet label Oct 12, 2020
@maribu
Copy link
Member Author

maribu commented Oct 12, 2020

Ups, I somehow squashed two commits accidentally

@maribu maribu force-pushed the stm32-eth-negotiate branch 2 times, most recently from f1fac00 to 5a94012 Compare October 12, 2020 09:15
@maribu
Copy link
Member Author

maribu commented Oct 12, 2020

Ups, I somehow squashed two commits accidentally

Split back up.

@maribu
Copy link
Member Author

maribu commented Oct 12, 2020

@kfessel: Since you reported the bug this PR fixes, do you care to test?

@kfessel
Copy link
Contributor

kfessel commented Oct 12, 2020

@maribu: There seems some debugging enabled in your pr – disabled it: /RIOT/cpu/stm32/periph/eth.c

I did test on BOARD=nucleo-f767zi

Test:
In 50 manual –and therefor with "random" reset timings– tries I had no failed initialization but it seems as if the startup did take different times (mostly (2 to 5 seconds)) (maybe the time difference is what threw of the old driver in its initialization –the longer times where much rarer)

Before I started to count to 50 I had one time where it seemed to not have initialized but this could also be that i got caught by a very long taking initialization (> a couple of seconds)

Before this patch i had at least one failed Initialization in 10 tries (i checked just before and kept everything but the Riot branch (master vs this pr) the same)
I did not change the Makefile and have neither USEMODULE += stm32_eth_link_up nor USEMODULE += stm32_eth_auto

my test verdict:
From my point of view this PR improves the situation and i would close my issue #13490 after that since the only failed attempt might be just my impatience

@benpicco benpicco removed the State: waiting for other PR State: The PR requires another PR to be merged first label Oct 12, 2020
Previously, only an link-up event was triggered, not an link down event. And
additionally, once the link-up event was sent, the link status was no longer
monitored. As a result, once a link-up was sent, no further link event were
triggered.
@maribu maribu force-pushed the stm32-eth-negotiate branch from 5a94012 to fc19219 Compare October 12, 2020 12:53
@maribu
Copy link
Member Author

maribu commented Oct 12, 2020

Rebased and fixed the accidental change of ENABLE_DEBUG.

@kfessel: I have no idea why the boot is delayed by that amount of time. The driver now just waits for the PHY to reset, which shouldn't be a matter of seconds. But maybe it is :-/

@kfessel
Copy link
Contributor

kfessel commented Oct 12, 2020

I would also think the PHY reset takes different times

i added:

    static int once = 0;
    if(!once){
        printf("eth_isr: %u\n", xtimer_now() );
        once = 1;
    }

to static void stm32_eth_isr(netdev_t *netdev) to print the xtime of the first interrupt (i think this is the end of the initialisation since the linkup stuff also uses this)

2020-10-12 15:52:29,532 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:52:29,533 # RIOT iwasm_gcoap
2020-10-12 15:52:29,535 # My address is
2020-10-12 15:52:29,537 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:52:31,758 # eth_isr: 2231879
2020-10-12 15:52:32,948 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:52:32,949 # RIOT iwasm_gcoap
2020-10-12 15:52:32,950 # My address is
2020-10-12 15:52:32,953 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:52:32,964 # eth_isr: 21572
2020-10-12 15:52:35,200 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:52:35,201 # RIOT iwasm_gcoap
2020-10-12 15:52:35,202 # My address is
2020-10-12 15:52:35,205 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:52:38,593 # eth_isr: 3399127
2020-10-12 15:52:39,471 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:52:39,473 # RIOT iwasm_gcoap
2020-10-12 15:52:39,474 # My address is
2020-10-12 15:52:39,477 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:52:42,842 # eth_isr: 3375959
2020-10-12 15:52:43,806 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:52:43,807 # RIOT iwasm_gcoap
2020-10-12 15:52:43,808 # My address is
2020-10-12 15:52:43,811 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:52:47,140 # eth_isr: 3339384
2020-10-12 15:52:48,558 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:52:48,559 # RIOT iwasm_gcoap
2020-10-12 15:52:48,560 # My address is
2020-10-12 15:52:48,563 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:52:51,612 # eth_isr: 3059476
2020-10-12 15:52:53,121 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:52:53,122 # RIOT iwasm_gcoap
2020-10-12 15:52:53,124 # My address is
2020-10-12 15:52:53,126 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:52:56,214 # eth_isr: 3098185

then is start t pings every 200ms similar behavior (does not depend on whether there is data or not)

2020-10-12 15:53:21,639 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:53:21,641 # RIOT iwasm_gcoap
2020-10-12 15:53:21,642 # My address is
2020-10-12 15:53:21,644 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:53:24,817 # eth_isr: 3183448
2020-10-12 15:53:25,352 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:53:25,354 # RIOT iwasm_gcoap
2020-10-12 15:53:25,355 # My address is
2020-10-12 15:53:25,357 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:53:28,472 # eth_isr: 3124697
2020-10-12 15:53:29,177 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:53:29,178 # RIOT iwasm_gcoap
2020-10-12 15:53:29,180 # My address is
2020-10-12 15:53:29,182 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:53:32,197 # eth_isr: 3025896
2020-10-12 15:53:33,007 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:53:33,008 # RIOT iwasm_gcoap
2020-10-12 15:53:33,009 # My address is
2020-10-12 15:53:33,012 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:53:36,278 # eth_isr: 3276972
2020-10-12 15:53:37,700 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:53:37,701 # RIOT iwasm_gcoap
2020-10-12 15:53:37,703 # My address is
2020-10-12 15:53:37,705 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:53:40,789 # eth_isr: 3094773
2020-10-12 15:53:41,723 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:53:41,725 # RIOT iwasm_gcoap
2020-10-12 15:53:41,726 # My address is
2020-10-12 15:53:41,728 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:53:45,081 # eth_isr: 3363365
2020-10-12 15:53:45,813 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:53:45,814 # RIOT iwasm_gcoap
2020-10-12 15:53:45,816 # My address is
2020-10-12 15:53:45,818 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:53:48,965 # eth_isr: 3157720
2020-10-12 15:53:50,538 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:53:50,540 # RIOT iwasm_gcoap
2020-10-12 15:53:50,546 # My address is
2020-10-12 15:53:50,547 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:53:53,486 # eth_isr: 2952685
2020-10-12 15:53:56,638 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:53:56,639 # RIOT iwasm_gcoap
2020-10-12 15:53:56,640 # My address is
2020-10-12 15:53:56,643 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:53:59,564 # eth_isr: 2931626
2020-10-12 15:54:00,939 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:54:00,941 # RIOT iwasm_gcoap
2020-10-12 15:54:00,947 # My address is
2020-10-12 15:54:00,948 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:54:02,673 # eth_isr: 1739144
2020-10-12 15:54:27,423 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:54:27,425 # RIOT iwasm_gcoap
2020-10-12 15:54:27,426 # My address is
2020-10-12 15:54:27,428 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:54:28,388 # eth_isr: 969806
2020-10-12 15:54:30,173 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:54:30,175 # RIOT iwasm_gcoap
2020-10-12 15:54:30,176 # My address is
2020-10-12 15:54:30,178 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:54:32,365 # eth_isr: 2197058
2020-10-12 15:54:33,193 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:54:33,194 # RIOT iwasm_gcoap
2020-10-12 15:54:33,196 # My address is
2020-10-12 15:54:33,198 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:54:36,104 # eth_isr: 2916870
2020-10-12 15:54:39,411 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:54:39,412 # RIOT iwasm_gcoap
2020-10-12 15:54:39,414 # My address is
2020-10-12 15:54:39,416 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:54:44,388 # eth_isr: 4982666
2020-10-12 15:54:46,342 # main(): This is RIOT! (Version: 2021.01-devel-118-g5a940-pr-mar-15203)
2020-10-12 15:54:46,344 # RIOT iwasm_gcoap
2020-10-12 15:54:46,345 # My address is
2020-10-12 15:54:46,348 # fe80:xxxxxxxxxxxxxxxx4
2020-10-12 15:54:49,500 # eth_isr: 3162779

P.S.: while doing this i got one no initialization and saw that the reset was to short to reset the STM32 completely (random manual very (to) short)

@kfessel
Copy link
Contributor

kfessel commented Oct 12, 2020

@maribu since this xtime is very random it may be a good entropy for pseudo random initialisation

@kfessel
Copy link
Contributor

kfessel commented Oct 17, 2020

@marian you should check default configuration since unused static function is consider an error:

<RIOT>/cpu/stm32/periph/eth.c:279:13: error: '_complete_auto_negotiation' defined but not used [-Werror=unused-function]
 static void _complete_auto_negotiation(void) 

rebased and testing for the error I disussed with you

Copy link
Contributor

@benpicco benpicco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good and @kfessel confirmed it working - please squash.

@maribu maribu force-pushed the stm32-eth-negotiate branch from 9366448 to b602dca Compare October 21, 2020 19:33
Expose the auto-negotiation feature of the Ethernet device via the
pseudo-module stm32_eth_auto. With this enabled, the static speed configuration
set in the boards periph_conf.h will only be used if the PHY lacks
auto-negotiation capabilities - which is unlikely to ever happen.
@maribu maribu force-pushed the stm32-eth-negotiate branch from b602dca to 5f9b55a Compare October 22, 2020 10:37
@maribu maribu added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Oct 22, 2020
@benpicco benpicco merged commit ad294aa into RIOT-OS:master Oct 23, 2020
@maribu
Copy link
Member Author

maribu commented Oct 23, 2020

Thanks :-)

@maribu maribu deleted the stm32-eth-negotiate branch October 23, 2020 15:40
@jia200x jia200x changed the title cpu/stm32: periph_eth: Use auto-negotation cpu/stm32: periph_eth: Use auto-negotiation Feb 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: cpu Area: CPU/MCU ports CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

cpu/stm32/eth, board/nucleo-f767z1: ethernet initialisation fails sometimes
3 participants