Skip to content

Conversation

@ianic
Copy link
Contributor

@ianic ianic commented Dec 26, 2025

In this pr I'm adding alternative cyw43 driver implementation. The one we currently have is great work and more complete. This alternative one is more optimized for lwip integration, I spent some time iterating on it to fit it into lwip worldview. I think that there are some good ideas in it so let me explain the optimizations.

Current one, as wall as embassy-rs, uses lot of internal buffers, 8320 bytes in total. In alternative implementation I eliminated all internal buffers, lwip has some nice features which can be used for that.
Besides memory usage that eliminates also memory copy. Currently it will be needed 3 mem copies to get network payload from wifi chip into lwip packet buffer, and one memcpy on send. Using lwip packet buffers all that can be eliminated.

Lwip can be configured to use pool of packet buffers. That is defined in lwipopts.h, for example:

#define MEM_ALIGNMENT 4
#define PBUF_POOL_SIZE 32      // number of preallocated buffers
#define PBUF_POOL_BUFSIZE 1540 // enough for 1500 MTU + headers (14 + 22 + 4)
#define PBUF_LINK_HLEN 14
#define PBUF_LINK_ENCAPSULATION_HLEN 22 // CYW43 WiFi header space

In netif_init we also set netif.mtu = 1500.

MEM_ALIGNMENT allows us to use packet buffers in u32 dma. mtu defines max layer 3 payload, lwip will add 14 bytes of ethernet header resulting in max 1514 bytes. PBUF_LINK_ENCAPSULATION_HLEN reserves 22 bytes at the front of each packet buffer. lwip will write ethernet header at position 22, and leave leading 22 bytes for use in the link (cyw43) interface.

c.pbuf_header(pbuf, 22) uncovers that 22 bytes in the packet buffer, moves payload pointer and adjusts len, tot_len. ref

22 bytes are enough to fit 4 bytes of spi command and 18 bytes of bus header. When we add those bytes at the front we can pass the same buffer to the dma avoiding all copies.

For reading we allocate raw packet buffer, pass all 1540 bytes to the driver and than to dma. Leading 22 bytes will be bus header (18 bytes + 4 bytes padding), then max 1514 bytes of ethernet packet and 4 bytes of dma status (so we can have just one dma read request). After parsing bus header we know how to adjust packet buffer payload start pointer and payload len. We set that and pass the same buffer to the netif input. ref

Example:

raspberrypi/rp2xxx/src/net/dhcp.zig initializes cyw43 driver, joins wifi network. You must add secrets.zig file with content:

pub const ssid = "...";
pub const pwd = "...";

lwip will then use dhcp to get ip address, when it is printed in log you can ping that ip, lwip will respond to ping requests.

In raspberrypi/rp2xxx/src/net/lwip/include folder is lwip configuration,
raspberrypi/rp2xxx/src/net/lwip/exports.zig is platform dependent (time, random) functions for lwip,
raspberrypi/rp2xxx/src/net/lwip/net.zig is core of the lwip integration, it is platform independent, link layer needs to provide 3 functions: send, recv, ready

@mattnite mattnite force-pushed the lwip2 branch 2 times, most recently from 77ec46c to b32aff8 Compare December 27, 2025 08:18
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

🔍 Lint Results

Found 6 issues on changed lines in 4 files:

  • drivers/wireless/cyw43439/bus.zig: 2 issues
  • drivers/wireless/cyw43439/ioctl.zig: 2 issues
  • drivers/wireless/cyw43439/wifi.zig: 1 issue
  • port/raspberrypi/rp2xxx/src/hal/cyw43439_pio_spi.zig: 1 issue
ℹ️ Additional issues on unchanged lines
The following 5 issue(s) exist but are not on lines changed in this PR:

drivers/framework.zig:87: TODO style comments need to have a linked microzig issue on the same line.
drivers/framework.zig:117: TODO style comments need to have a linked microzig issue on the same line.
drivers/framework.zig:151: TODO style comments need to have a linked microzig issue on the same line.
drivers/framework.zig:164: TODO style comments need to have a linked microzig issue on the same line.
port/raspberrypi/rp2xxx/src/hal/drivers.zig:478: TODO style comments need to have a linked microzig issue on the same line.

@mattnite
Copy link
Contributor

@ianic along with the linting changes and formatting, please find a way to implement that secrets file. Put dummy data in there for now, and include documentation on how to update them, or find some other way to encode that data.

@github-actions github-actions bot dismissed their stale review December 27, 2025 11:33

Updating with new lint results

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

🔍 Lint Results

ℹ️ Additional issues on unchanged lines
The following 5 issue(s) exist but are not on lines changed in this PR:

drivers/framework.zig:87: TODO style comments need to have a linked microzig issue on the same line.
drivers/framework.zig:117: TODO style comments need to have a linked microzig issue on the same line.
drivers/framework.zig:151: TODO style comments need to have a linked microzig issue on the same line.
drivers/framework.zig:164: TODO style comments need to have a linked microzig issue on the same line.
port/raspberrypi/rp2xxx/src/hal/drivers.zig:478: TODO style comments need to have a linked microzig issue on the same line.

@arkadiuszwojcik
Copy link
Contributor

@ianic excellent work! I am taking a look right now, my first question is regarding lwip package source:

//.url = "https://download.savannah.nongnu.org/releases/lwip/lwip-2.1.3.zip",
.url = "https://github.com/Ashet-Technologies/deps/raw/refs/heads/main/lwip-2.1.3.zip",

looks like download.savannah.nongnu.org is not stable, right now is down so this is why it was commented out. Maybe this: https://github.com/lwip-tcpip/lwip/tags should be use instead? New version is 2.2.1 but for now to not complicate things 2.1.3 could be used.

@ianic
Copy link
Contributor Author

ianic commented Dec 27, 2025

I copied that from AshetOS. If you look at the history the reason was "selfhosted mirror as above download can't serve tls for zig". It probably is not the case any more (once zig tls was 1.3 only).

https://github.com/Ashet-Technologies/Ashet-OS/tree/master/vendor/lwip

https://github.com/Ashet-Technologies/Ashet-OS/blob/23ae2e7740dbadf4b078e9f97680494bd9ddd8ef/src/kernel/components/network.zig

I have plan to try upgrade to the latest lwip.

Copy link
Contributor

@mattnite mattnite left a comment

Choose a reason for hiding this comment

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

This looks great! We can fetch from AshetOS for the time being

@mattnite mattnite merged commit ce9d4a6 into ZigEmbeddedGroup:main Dec 28, 2025
47 of 49 checks passed
@ianic ianic mentioned this pull request Jan 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants