Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

driver/w5500: driver for the W5500 ethernet chip #20301

Merged
merged 1 commit into from
May 3, 2024

Conversation

stemschmidt
Copy link
Contributor

Contribution description

This is a driver for a WIZ5500 ethernet chip. The driver supports interrupt and polling mode. Polling mode is the default, as plugging the Adafruit Ethernet FeatherWing on the Adafruit nrf52840 Feather requires no additional wiring for the interrupt pin.

Provide a definition for W5500_PARAM_EVT to enable the interrupt mode.

Testing procedure

Build:
make BOARD=feather-nrf52840 -C tests/drivers/w5500/ flash term

Ping ipv6.google.com:
2024-01-26 18:08:37,885 # : This is RIOT! (Version: a74a7-driver_w5500)
2024-01-26 18:08:37,887 # Test application for W5500 ethernet device driver
2024-01-26 18:08:37,889 # All up, running the shell now

ping 2a00:1450:4016:808::200e
2024-01-26 18:08:58,580 # ping 2a00:1450:4016:808::200e
2024-01-26 18:08:58,775 # 12 bytes from 2a00:1450:4016:808::200e: icmp_seq=0 ttl=118 time=192.157 ms
2024-01-26 18:08:59,675 # 12 bytes from 2a00:1450:4016:808::200e: icmp_seq=1 ttl=118 time=92.177 ms
2024-01-26 18:09:00,675 # 12 bytes from 2a00:1450:4016:808::200e: icmp_seq=2 ttl=118 time=92.203 ms
2024-01-26 18:09:00,676 #
2024-01-26 18:09:00,678 # --- 2a00:1450:4016:808::200e PING statistics ---
2024-01-26 18:09:00,680 # 3 packets transmitted, 3 packets received, 0% packet loss
2024-01-26 18:09:00,682 # round-trip min/avg/max = 92.177/125.512/192.157 ms

@github-actions github-actions bot added Area: network Area: Networking Area: tests Area: tests and testing framework Area: drivers Area: Device drivers Area: sys Area: System Area: Kconfig Area: Kconfig integration labels Jan 26, 2024
@benpicco benpicco added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Jan 26, 2024
@riot-ci
Copy link

riot-ci commented Jan 26, 2024

Murdock results

✔️ PASSED

9d62ad4 driver/w5500: driver for the W5500 ethernet chip

Success Failures Total Runtime
10082 0 10083 13m:14s

Artifacts

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.

Thank you for the driver!
This looks quite good already, just some comments:

*/
enum {
W5500_ERR_BUS = -1,
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do you need this?

Copy link
Contributor Author

@stemschmidt stemschmidt Jan 27, 2024

Choose a reason for hiding this comment

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

This is returned if the device cannot be accessed via I2C bus

Copy link
Contributor

Choose a reason for hiding this comment

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

I mean why a custom error code instead something from errno.h

Copy link
Contributor Author

@stemschmidt stemschmidt Feb 2, 2024

Choose a reason for hiding this comment

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

Ok, I switch to -ENODEV

netdev_t netdev; /**< extends the netdev structure */
w5500_params_t p; /**< device configuration parameters */
uint16_t frame_size_to_be_send;
uint16_t frame_size_sent;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why would they differ?

Copy link
Contributor Author

@stemschmidt stemschmidt Jan 27, 2024

Choose a reason for hiding this comment

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

My understanding of confirm_send is that this function can be called at any time to get the number of transmitted bytes of the current frame:

  1. called before a new transmission is started (frame_size_to_be_send = 0): return the transferred size of the previous frame (frame_size_sent)
  2. called after the new transmission has been started and is still in progress (frame_size_sent = 0): return -EAGAIN
  3. called after the new transmission terminated -> see 1.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the intention here was that this would only be called after the transmission and that the beginning of a new transmission would invalidate it (returns -EAGAIN).

So there is no need to store the size of the previous transmission.

But @maribu should know best.

Copy link
Member

Choose a reason for hiding this comment

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

As @benpicco said:

  1. Call send(), it returns right away, the hardware transmits in background
  2. Wait for transmission to complete
  3. Call confirm_send() exactly once to get the number of transmitted bytes or the error code

Copy link
Member

Choose a reason for hiding this comment

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

Note: The is a provision for trivial polling:

send();
while ((result = confirm_send) == -EAGAIN) {
    /* polling for TX to complete */
}
/* transmission result is in result */

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I understand. I thought you might be able to poll the current number of transmitted bytes of the frame while the transmission is still ongoing (the hardware might transmit the frame in chunks, so you could get the number of bytes already transmitted)...
I will change the implementation.

drivers/w5500/w5500.c Outdated Show resolved Hide resolved
drivers/w5500/w5500.c Outdated Show resolved Hide resolved
drivers/w5500/w5500.c Outdated Show resolved Hide resolved
drivers/w5500/w5500.c Outdated Show resolved Hide resolved

uint8_t tmp = rreg(dev, REG_PHYCFGR);

if (tmp & PHY_LINK_UP) {
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you need dev->link_up for then? It's never read.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is read in isr() in order to send NETDEV_EVENT_LINK_UP and NETDEV_EVENT_LINK_DOWN only when the status has change

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah so a change in link status does not cause an interrupt on it's own?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I could not find a way to trigger an interrupt when the PHY state changes. So I poll it in several places.

drivers/w5500/w5500.c Outdated Show resolved Hide resolved
drivers/w5500/w5500.c Outdated Show resolved Hide resolved
drivers/w5500/w5500.c Show resolved Hide resolved
@stemschmidt stemschmidt force-pushed the driver_w5500 branch 2 times, most recently from b423975 to 63d5c41 Compare January 28, 2024 17:05
Comment on lines 149 to 153
/* Polling mode: W5500_PARAM_EVT == GPIO_UNDEF and polling_interval_ms > 0u */
/* Interrupt mode: W5500_PARAM_EVT != GPIO_UNDEF and polling_interval_ms == 0u */
return((dev->p.evt == GPIO_UNDEF && dev->p.polling_interval_ms > 0u) ||
(dev->p.evt != GPIO_UNDEF && dev->p.polling_interval_ms == 0u));
}
Copy link
Contributor

@benpicco benpicco Jan 29, 2024

Choose a reason for hiding this comment

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

I'd be a bit more graceful here: You could have a valid polling interval always configured by default, but when a IRQ pin is provided use that instead of polling (and instead of producing an unnecessary error on init).

I can't think of a use case where you would want polling if you have an IRQ pin.

Copy link
Contributor Author

@stemschmidt stemschmidt Feb 2, 2024

Choose a reason for hiding this comment

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

Ok. My intention was to point the user to the invalid configuration, but I have softened the edge now :-) And removed the function.

tmp = read_register(dev, REG_VERSIONR);
if (tmp != CHIP_VERSION) {
spi_release(dev->p.spi);
LOG_ERROR("[w5500] error: no SPI connection\n");
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
LOG_ERROR("[w5500] error: no SPI connection\n");
LOG_ERROR("[w5500] error: invalid chip ID %x\n", tmp);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed!

Copy link
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

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

Thanks for the PR :)

First round of comments

sys/net/gnrc/netif/init_devs/auto_init_w5500.c Outdated Show resolved Hide resolved
drivers/w5500/w5500.c Outdated Show resolved Hide resolved
drivers/w5500/w5500.c Outdated Show resolved Hide resolved
@maribu maribu mentioned this pull request Jan 30, 2024
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.

Sorry for the delay, some more nits:

drivers/w5500/include/w5500_params.h Outdated Show resolved Hide resolved
drivers/w5500/w5500.c Outdated Show resolved Hide resolved
drivers/w5500/w5500.c Show resolved Hide resolved
spi_clk_t clk; /**< clock speed used on the selected SPI bus */
gpio_t cs; /**< pin connected to the chip select line */
gpio_t evt; /**< pin connected to the INT line */
uint32_t polling_interval_ms; /**< interval for polling, 0 if interrupt mode */
Copy link
Contributor

Choose a reason for hiding this comment

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

Have you considered doing a compile-time check, so we don't even need to compile the polling code in if we have a IRQ pin connected?

Suggested change
uint32_t polling_interval_ms; /**< interval for polling, 0 if interrupt mode */
#if W5500_PARAM_EVT == GPIO_UNDEF
uint32_t polling_interval_ms; /**< interval for polling, 0 if interrupt mode */
#endif

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The w5500.h header is independent of the configuration, it does not include w5500_params.h. So I do not have the information W5500_PARAM_IRQ == GPIO_UNDEF available in the header

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.

Sorry for the delay, I think this driver is fine if it works for you.

Just some small nits, please squash directly.

tests/drivers/w5500/Makefile Outdated Show resolved Hide resolved
tests/drivers/w5500/Makefile Outdated Show resolved Hide resolved
tests/drivers/w5500/Makefile Outdated Show resolved Hide resolved
tests/drivers/w5500/Makefile Outdated Show resolved Hide resolved
drivers/w5500/w5500.c Outdated Show resolved Hide resolved
@stemschmidt stemschmidt force-pushed the driver_w5500 branch 3 times, most recently from 8801a71 to 2eaebc4 Compare April 24, 2024 20:37
@benpicco
Copy link
Contributor

benpicco commented Apr 24, 2024

The changes to the example Makefile still apply 😉
Why not just use the example app from tests/drivers/w5100 and change w5100 -> w5500?

@benpicco benpicco added this pull request to the merge queue Apr 26, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Apr 26, 2024
@stemschmidt
Copy link
Contributor Author

Hi @benpicco, could you please help me with the failing release-tests? Where do I find information about the "Invalid access token passed." message?

@maribu
Copy link
Member

maribu commented Apr 27, 2024

The issue is that the new test app fails to link on some boards. The CI stopped building on the first instance, which was the ATmega8.

This is expected, as some MCUs (like the ATmega8) just have too little RAM and/or ROM to allow running the app. We manually keep a list of boards that are expected to fail linking in the Makefile.ci. You can run make generate-Makefile.ci in the test folder to update/generate that file.

Note: You might need to run docker pull riot/riotbuild first to update the docker image with the versions used in the CI, as different compiler versions optimize the code differently, resulting in some apps that barely fit with one to overflow with the other.

@maribu
Copy link
Member

maribu commented Apr 27, 2024

You can directly squash the update of the Makefile.ci into the commit that adds the app.

Note: I can also run the script tonight. Building an app 200+ times burns a few CPU cycles (we have a lot of boards supported these days 😎)

@maribu
Copy link
Member

maribu commented Apr 28, 2024

Please tick the checkbox that allow maintainers to edit this PR, otherwise I'm unable to push the Makefile.ci update.

@maribu
Copy link
Member

maribu commented Apr 28, 2024

Or alternatively, store this as Makefile.ci in the test app:

BOARD_INSUFFICIENT_MEMORY := \
    arduino-duemilanove \
    arduino-leonardo \
    arduino-nano \
    arduino-uno \
    atmega328p \
    atmega328p-xplained-mini \
    atmega8 \
    nucleo-f031k6 \
    nucleo-l011k4 \
    samd10-xmini \
    stk3200 \
    stm32f030f4-demo \
    #

Please also note: The commit message is syntactically incorrect. There is missing a mandatory blank line between the header and the body of the commit message.

@stemschmidt
Copy link
Contributor Author

Please tick the checkbox that allow maintainers to edit this PR, otherwise I'm unable to push the Makefile.ci update.

Mmmh, I can't see the checkbox...

grafik

@maribu
Copy link
Member

maribu commented Apr 30, 2024

I think you are looking at the right spot in the page. It looks like this for me:

20240430_14h02m17s_grim

Are you logged in?

In either case, just storing the content from two messages above in a file named Makefile.ci in the test app would get this past the CI as well ;)

Please don't forget to add a blank line after the header (the first line) in the commit message when you --amend the commit.

@stemschmidt
Copy link
Contributor Author

I will update the makefile.in later or tomorrow...

@stemschmidt stemschmidt force-pushed the driver_w5500 branch 2 times, most recently from a126323 to 87612aa Compare April 30, 2024 21:11
@stemschmidt
Copy link
Contributor Author

Ok, I added the Makefile.in and modified the commit message... Now fingers crossed :-)

@maribu maribu enabled auto-merge May 1, 2024 05:55
@maribu maribu added this pull request to the merge queue May 1, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks May 1, 2024
@stemschmidt
Copy link
Contributor Author

Mmmh, why is it still being build for the atmega8? And also for other cpus/boards in the insufficient-memory list?

Copy link
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

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

The list of boards to skip the linking step for should go into Makefile.ci, not Makefile.in. Sorry for the confusion.

Comment on lines 1 to 29
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
bluepill-stm32f030c8 \
i-nucleo-lrwan1 \
msb-430 \
msb-430h \
nucleo-f030r8 \
nucleo-f031k6 \
nucleo-f042k6 \
nucleo-f303k8 \
nucleo-f334r8 \
nucleo-l011k4 \
nucleo-l031k6 \
nucleo-l053r8 \
samd10-xmini \
slstk3400a \
stk3200 \
stm32f030f4-demo \
stm32f0discovery \
stm32l0538-disco \
waspmote-pro \
#
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
bluepill-stm32f030c8 \
i-nucleo-lrwan1 \
msb-430 \
msb-430h \
nucleo-f030r8 \
nucleo-f031k6 \
nucleo-f042k6 \
nucleo-f303k8 \
nucleo-f334r8 \
nucleo-l011k4 \
nucleo-l031k6 \
nucleo-l053r8 \
samd10-xmini \
slstk3400a \
stk3200 \
stm32f030f4-demo \
stm32f0discovery \
stm32l0538-disco \
waspmote-pro \
#
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
atmega8 \
nucleo-f031k6 \
nucleo-l011k4 \
samd10-xmini \
stk3200 \
stm32f030f4-demo \
#

@@ -0,0 +1,14 @@
BOARD_INSUFFICIENT_MEMORY := \
Copy link
Member

Choose a reason for hiding this comment

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

This file should be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok, I will do it later today...

Copy link
Contributor Author

@stemschmidt stemschmidt May 2, 2024

Choose a reason for hiding this comment

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

Ok, I have modified the Makefile.ci and removed the Makefile.in (I have added the missing boards to the existing Makefile.ci)... If I had used my brain I could have come up with the idea that the Makefile.ci is the relevant file :-)

- driver can be used with interrupt or in polling mode (default)
@maribu maribu enabled auto-merge May 2, 2024 20:53
@maribu maribu disabled auto-merge May 3, 2024 06:12
@maribu maribu enabled auto-merge May 3, 2024 06:12
@maribu maribu added this pull request to the merge queue May 3, 2024
Merged via the queue into RIOT-OS:master with commit e244918 May 3, 2024
26 checks passed
@stemschmidt stemschmidt deleted the driver_w5500 branch May 3, 2024 09:12
@maribu
Copy link
Member

maribu commented May 3, 2024

It finally is in 🎉 Sometimes it really is a bit of a pain to get a PR past the CI 😦

Thanks a lot for your pull request!

@stemschmidt
Copy link
Contributor Author

Yeah :-)

I am impressed by the RIOT CI chain, I think it is a great (or maybe the best) way to define what is expected from a piece of software before it can be merged into main.

I think it is a bit difficult to keep track of what is missing and how things are handled if you are not working 100% of your time on the Repository, but finally it is in the main!!!

@mguetschow mguetschow added this to the Release 2024.07 milestone Jul 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: drivers Area: Device drivers Area: Kconfig Area: Kconfig integration Area: network Area: Networking Area: sys Area: System Area: tests Area: tests and testing framework CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants