aboutsummaryrefslogtreecommitdiff
path: root/embassy-net-driver-channel
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-10-16 23:41:58 +0200
committerDario Nieuwenhuis <[email protected]>2023-10-18 05:28:16 +0200
commit3cbc6874247d7b814cab8ec8762bfe2f6f385828 (patch)
treeaac4c615c816f6465559874a98c9d3cf60c21817 /embassy-net-driver-channel
parent51708c8ed1962618ac7bc244a3f5e7ceced28182 (diff)
net/driver: remove Medium, make HardwareAddress non_exhaustive.
Diffstat (limited to 'embassy-net-driver-channel')
-rw-r--r--embassy-net-driver-channel/CHANGELOG.md10
-rw-r--r--embassy-net-driver-channel/README.md18
-rw-r--r--embassy-net-driver-channel/src/lib.rs20
3 files changed, 16 insertions, 32 deletions
diff --git a/embassy-net-driver-channel/CHANGELOG.md b/embassy-net-driver-channel/CHANGELOG.md
index 589996cfd..b04d0a86b 100644
--- a/embassy-net-driver-channel/CHANGELOG.md
+++ b/embassy-net-driver-channel/CHANGELOG.md
@@ -5,14 +5,12 @@ All notable changes to this project will be documented in this file.
5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 7
8## 0.2.0 - 2023-10-15 8## 0.2.0 - 2023-10-18
9 9
10- Update embassy-net-driver 10- Update `embassy-net-driver` to v0.2
11- `Runner::new` now takes an `embassy_net_driver::HardwareAddress` parameter 11- `Runner::new` now takes an `embassy_net_driver::HardwareAddress` parameter.
12- Added `Runner::set_ieee802154_address`, `Runner::ieee802154_address` 12- `Runner::set_ethernet_address` is now `set_hardware_address`.
13 13
14## 0.1.0 - 2023-06-29 14## 0.1.0 - 2023-06-29
15 15
16- First release 16- First release
17
18
diff --git a/embassy-net-driver-channel/README.md b/embassy-net-driver-channel/README.md
index 8f904ce95..90a216388 100644
--- a/embassy-net-driver-channel/README.md
+++ b/embassy-net-driver-channel/README.md
@@ -7,7 +7,9 @@ The `embassy-net-driver` trait is polling-based. To implement it, you must write
7hand, and hook up the `Waker`s provided by `embassy-net` to the right interrupt handlers so that `embassy-net` 7hand, and hook up the `Waker`s provided by `embassy-net` to the right interrupt handlers so that `embassy-net`
8knows when to poll your driver again to make more progress. 8knows when to poll your driver again to make more progress.
9 9
10With `embassy-net-driver-channel` 10With `embassy-net-driver-channel` you get a "channel-like" interface instead, where you can send/receive packets
11to/from embassy-net. The intended usage is to spawn a "driver task" in the background that does this, passing
12packets between the hardware and the channel.
11 13
12## A note about deadlocks 14## A note about deadlocks
13 15
@@ -18,19 +20,19 @@ loop {
18 // Wait for either.. 20 // Wait for either..
19 match select( 21 match select(
20 // ... the chip signaling an interrupt, indicating a packet is available to receive, or 22 // ... the chip signaling an interrupt, indicating a packet is available to receive, or
21 irq_pin.wait_for_low(), 23 irq_pin.wait_for_low(),
22 // ... a TX buffer becoming available, i.e. embassy-net wants to send a packet 24 // ... a TX buffer becoming available, i.e. embassy-net wants to send a packet
23 tx_chan.tx_buf(), 25 tx_chan.tx_buf(),
24 ).await { 26 ).await {
25 Either::First(_) => { 27 Either::First(_) => {
26 // a packet is ready to be received! 28 // a packet is ready to be received!
27 let buf = rx_chan.rx_buf().await; // allocate a rx buf from the packet queue 29 let buf = rx_chan.rx_buf().await; // allocate a rx buf from the packet queue
28 let n = receive_packet_over_spi(buf).await; 30 let n = receive_packet_over_spi(buf).await;
29 rx_chan.rx_done(n); 31 rx_chan.rx_done(n);
30 } 32 }
31 Either::Second(buf) => { 33 Either::Second(buf) => {
32 // a packet is ready to be sent! 34 // a packet is ready to be sent!
33 send_packet_over_spi(buf).await; 35 send_packet_over_spi(buf).await;
34 tx_chan.tx_done(); 36 tx_chan.tx_done();
35 } 37 }
36 } 38 }
@@ -41,7 +43,7 @@ However, this code has a latent deadlock bug. The symptom is it can hang at `rx_
41 43
42The reason is that, under load, both the TX and RX queues can get full at the same time. When this happens, the `embassy-net` task stalls trying to send because the TX queue is full, therefore it stops processing packets in the RX queue. Your driver task also stalls because the RX queue is full, therefore it stops processing packets in the TX queue. 44The reason is that, under load, both the TX and RX queues can get full at the same time. When this happens, the `embassy-net` task stalls trying to send because the TX queue is full, therefore it stops processing packets in the RX queue. Your driver task also stalls because the RX queue is full, therefore it stops processing packets in the TX queue.
43 45
44The fix is to make sure to always service the TX queue while you're waiting for space to become available in the TX queue. For example, select on either "tx_chan.tx_buf() available" or "INT is low AND rx_chan.rx_buf() available": 46The fix is to make sure to always service the TX queue while you're waiting for space to become available in the RX queue. For example, select on either "tx_chan.tx_buf() available" or "INT is low AND rx_chan.rx_buf() available":
45 47
46```rust,ignore 48```rust,ignore
47loop { 49loop {
@@ -58,12 +60,12 @@ loop {
58 ).await { 60 ).await {
59 Either::First(buf) => { 61 Either::First(buf) => {
60 // a packet is ready to be received! 62 // a packet is ready to be received!
61 let n = receive_packet_over_spi(buf).await; 63 let n = receive_packet_over_spi(buf).await;
62 rx_chan.rx_done(n); 64 rx_chan.rx_done(n);
63 } 65 }
64 Either::Second(buf) => { 66 Either::Second(buf) => {
65 // a packet is ready to be sent! 67 // a packet is ready to be sent!
66 send_packet_over_spi(buf).await; 68 send_packet_over_spi(buf).await;
67 tx_chan.tx_done(); 69 tx_chan.tx_done();
68 } 70 }
69 } 71 }
@@ -79,12 +81,10 @@ These `embassy-net` drivers are implemented using this crate. You can look at th
79- [`embassy-net-wiznet`](https://github.com/embassy-rs/embassy/tree/main/embassy-net-wiznet) for Wiznet SPI Ethernet MAC+PHY chips. 81- [`embassy-net-wiznet`](https://github.com/embassy-rs/embassy/tree/main/embassy-net-wiznet) for Wiznet SPI Ethernet MAC+PHY chips.
80- [`embassy-net-esp-hosted`](https://github.com/embassy-rs/embassy/tree/main/embassy-net-esp-hosted) for using ESP32 chips with the [`esp-hosted`](https://github.com/espressif/esp-hosted) firmware as WiFi adapters for another non-ESP32 MCU. 82- [`embassy-net-esp-hosted`](https://github.com/embassy-rs/embassy/tree/main/embassy-net-esp-hosted) for using ESP32 chips with the [`esp-hosted`](https://github.com/espressif/esp-hosted) firmware as WiFi adapters for another non-ESP32 MCU.
81 83
82
83## Interoperability 84## Interoperability
84 85
85This crate can run on any executor. 86This crate can run on any executor.
86 87
87
88## License 88## License
89 89
90This work is licensed under either of 90This work is licensed under either of
diff --git a/embassy-net-driver-channel/src/lib.rs b/embassy-net-driver-channel/src/lib.rs
index bf7ae5217..bfb2c9c03 100644
--- a/embassy-net-driver-channel/src/lib.rs
+++ b/embassy-net-driver-channel/src/lib.rs
@@ -8,9 +8,8 @@ use core::cell::RefCell;
8use core::mem::MaybeUninit; 8use core::mem::MaybeUninit;
9use core::task::{Context, Poll}; 9use core::task::{Context, Poll};
10 10
11use driver::HardwareAddress;
12pub use embassy_net_driver as driver; 11pub use embassy_net_driver as driver;
13use embassy_net_driver::{Capabilities, LinkState, Medium}; 12use embassy_net_driver::{Capabilities, LinkState};
14use embassy_sync::blocking_mutex::raw::NoopRawMutex; 13use embassy_sync::blocking_mutex::raw::NoopRawMutex;
15use embassy_sync::blocking_mutex::Mutex; 14use embassy_sync::blocking_mutex::Mutex;
16use embassy_sync::waitqueue::WakerRegistration; 15use embassy_sync::waitqueue::WakerRegistration;
@@ -161,18 +160,10 @@ impl<'d> StateRunner<'d> {
161 }); 160 });
162 } 161 }
163 162
164 pub fn set_ethernet_address(&self, address: [u8; 6]) { 163 pub fn set_hardware_address(&self, address: driver::HardwareAddress) {
165 self.shared.lock(|s| { 164 self.shared.lock(|s| {
166 let s = &mut *s.borrow_mut(); 165 let s = &mut *s.borrow_mut();
167 s.hardware_address = driver::HardwareAddress::Ethernet(address); 166 s.hardware_address = address;
168 s.waker.wake();
169 });
170 }
171
172 pub fn set_ieee802154_address(&self, address: [u8; 8]) {
173 self.shared.lock(|s| {
174 let s = &mut *s.borrow_mut();
175 s.hardware_address = driver::HardwareAddress::Ieee802154(address);
176 s.waker.wake(); 167 s.waker.wake();
177 }); 168 });
178 } 169 }
@@ -232,11 +223,6 @@ pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
232) -> (Runner<'d, MTU>, Device<'d, MTU>) { 223) -> (Runner<'d, MTU>, Device<'d, MTU>) {
233 let mut caps = Capabilities::default(); 224 let mut caps = Capabilities::default();
234 caps.max_transmission_unit = MTU; 225 caps.max_transmission_unit = MTU;
235 caps.medium = match &hardware_address {
236 HardwareAddress::Ethernet(_) => Medium::Ethernet,
237 HardwareAddress::Ieee802154(_) => Medium::Ieee802154,
238 HardwareAddress::Ip => Medium::Ip,
239 };
240 226
241 // safety: this is a self-referential struct, however: 227 // safety: this is a self-referential struct, however:
242 // - it can't move while the `'d` borrow is active. 228 // - it can't move while the `'d` borrow is active.