diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-12-27 01:19:26 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-12-27 01:19:26 +0100 |
| commit | 2548bbdd65fc3094f624bd043a1a9a296f9184b5 (patch) | |
| tree | f3b50c80846dfb077cf16e6a223e7602a3c4aa1a /src | |
| parent | 1b6799d93f0bbd6154c124d51aa47aeed0acf15d (diff) | |
Update Embassy.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib.rs | 218 |
1 files changed, 87 insertions, 131 deletions
diff --git a/src/lib.rs b/src/lib.rs index fa73b32e0..25e6f8f16 100644 --- a/src/lib.rs +++ b/src/lib.rs | |||
| @@ -15,14 +15,10 @@ mod structs; | |||
| 15 | use core::cell::Cell; | 15 | use core::cell::Cell; |
| 16 | use core::cmp::{max, min}; | 16 | use core::cmp::{max, min}; |
| 17 | use core::slice; | 17 | use core::slice; |
| 18 | use core::sync::atomic::Ordering; | ||
| 19 | use core::task::Waker; | ||
| 20 | 18 | ||
| 21 | use atomic_polyfill::AtomicBool; | 19 | use ch::driver::LinkState; |
| 22 | use embassy_futures::yield_now; | 20 | use embassy_futures::yield_now; |
| 23 | use embassy_net::{PacketBoxExt, PacketBuf}; | 21 | use embassy_net_driver_channel as ch; |
| 24 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 25 | use embassy_sync::channel::Channel; | ||
| 26 | use embassy_time::{block_for, Duration, Timer}; | 22 | use embassy_time::{block_for, Duration, Timer}; |
| 27 | use embedded_hal_1::digital::OutputPin; | 23 | use embedded_hal_1::digital::OutputPin; |
| 28 | use embedded_hal_async::spi::{SpiBusRead, SpiBusWrite, SpiDevice}; | 24 | use embedded_hal_async::spi::{SpiBusRead, SpiBusWrite, SpiDevice}; |
| @@ -32,6 +28,8 @@ use crate::consts::*; | |||
| 32 | use crate::events::Event; | 28 | use crate::events::Event; |
| 33 | use crate::structs::*; | 29 | use crate::structs::*; |
| 34 | 30 | ||
| 31 | const MTU: usize = 1514; | ||
| 32 | |||
| 35 | #[derive(Clone, Copy)] | 33 | #[derive(Clone, Copy)] |
| 36 | pub enum IoctlType { | 34 | pub enum IoctlType { |
| 37 | Get = 0, | 35 | Get = 0, |
| @@ -128,30 +126,25 @@ enum IoctlState { | |||
| 128 | 126 | ||
| 129 | pub struct State { | 127 | pub struct State { |
| 130 | ioctl_state: Cell<IoctlState>, | 128 | ioctl_state: Cell<IoctlState>, |
| 131 | 129 | ch: ch::State<MTU, 4, 4>, | |
| 132 | tx_channel: Channel<NoopRawMutex, PacketBuf, 8>, | ||
| 133 | rx_channel: Channel<NoopRawMutex, PacketBuf, 8>, | ||
| 134 | link_up: AtomicBool, | ||
| 135 | } | 130 | } |
| 136 | 131 | ||
| 137 | impl State { | 132 | impl State { |
| 138 | pub fn new() -> Self { | 133 | pub fn new() -> Self { |
| 139 | Self { | 134 | Self { |
| 140 | ioctl_state: Cell::new(IoctlState::Idle), | 135 | ioctl_state: Cell::new(IoctlState::Idle), |
| 141 | 136 | ch: ch::State::new(), | |
| 142 | tx_channel: Channel::new(), | ||
| 143 | rx_channel: Channel::new(), | ||
| 144 | link_up: AtomicBool::new(true), // TODO set up/down as we join/deassociate | ||
| 145 | } | 137 | } |
| 146 | } | 138 | } |
| 147 | } | 139 | } |
| 148 | 140 | ||
| 149 | pub struct Control<'a> { | 141 | pub struct Control<'a> { |
| 150 | state: &'a State, | 142 | state_ch: ch::StateRunner<'a>, |
| 143 | ioctl_state: &'a Cell<IoctlState>, | ||
| 151 | } | 144 | } |
| 152 | 145 | ||
| 153 | impl<'a> Control<'a> { | 146 | impl<'a> Control<'a> { |
| 154 | pub async fn init(&mut self, clm: &[u8]) -> NetDevice<'a> { | 147 | pub async fn init(&mut self, clm: &[u8]) { |
| 155 | const CHUNK_SIZE: usize = 1024; | 148 | const CHUNK_SIZE: usize = 1024; |
| 156 | 149 | ||
| 157 | info!("Downloading CLM..."); | 150 | info!("Downloading CLM..."); |
| @@ -258,12 +251,10 @@ impl<'a> Control<'a> { | |||
| 258 | 251 | ||
| 259 | Timer::after(Duration::from_millis(100)).await; | 252 | Timer::after(Duration::from_millis(100)).await; |
| 260 | 253 | ||
| 261 | info!("INIT DONE"); | 254 | self.state_ch.set_ethernet_address(mac_addr); |
| 255 | self.state_ch.set_link_state(LinkState::Up); // TODO do on join/leave | ||
| 262 | 256 | ||
| 263 | NetDevice { | 257 | info!("INIT DONE"); |
| 264 | state: self.state, | ||
| 265 | mac_addr, | ||
| 266 | } | ||
| 267 | } | 258 | } |
| 268 | 259 | ||
| 269 | pub async fn join_open(&mut self, ssid: &str) { | 260 | pub async fn join_open(&mut self, ssid: &str) { |
| @@ -381,75 +372,30 @@ impl<'a> Control<'a> { | |||
| 381 | async fn ioctl(&mut self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize { | 372 | async fn ioctl(&mut self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize { |
| 382 | // TODO cancel ioctl on future drop. | 373 | // TODO cancel ioctl on future drop. |
| 383 | 374 | ||
| 384 | while !matches!(self.state.ioctl_state.get(), IoctlState::Idle) { | 375 | while !matches!(self.ioctl_state.get(), IoctlState::Idle) { |
| 385 | yield_now().await; | 376 | yield_now().await; |
| 386 | } | 377 | } |
| 387 | 378 | ||
| 388 | self.state | 379 | self.ioctl_state.set(IoctlState::Pending { kind, cmd, iface, buf }); |
| 389 | .ioctl_state | ||
| 390 | .set(IoctlState::Pending { kind, cmd, iface, buf }); | ||
| 391 | 380 | ||
| 392 | let resp_len = loop { | 381 | let resp_len = loop { |
| 393 | if let IoctlState::Done { resp_len } = self.state.ioctl_state.get() { | 382 | if let IoctlState::Done { resp_len } = self.ioctl_state.get() { |
| 394 | break resp_len; | 383 | break resp_len; |
| 395 | } | 384 | } |
| 396 | yield_now().await; | 385 | yield_now().await; |
| 397 | }; | 386 | }; |
| 398 | 387 | ||
| 399 | self.state.ioctl_state.set(IoctlState::Idle); | 388 | self.ioctl_state.set(IoctlState::Idle); |
| 400 | 389 | ||
| 401 | resp_len | 390 | resp_len |
| 402 | } | 391 | } |
| 403 | } | 392 | } |
| 404 | 393 | ||
| 405 | pub struct NetDevice<'a> { | ||
| 406 | state: &'a State, | ||
| 407 | mac_addr: [u8; 6], | ||
| 408 | } | ||
| 409 | |||
| 410 | impl<'a> embassy_net::Device for NetDevice<'a> { | ||
| 411 | fn register_waker(&mut self, waker: &Waker) { | ||
| 412 | // loopy loopy wakey wakey | ||
| 413 | waker.wake_by_ref() | ||
| 414 | } | ||
| 415 | |||
| 416 | fn link_state(&mut self) -> embassy_net::LinkState { | ||
| 417 | match self.state.link_up.load(Ordering::Relaxed) { | ||
| 418 | true => embassy_net::LinkState::Up, | ||
| 419 | false => embassy_net::LinkState::Down, | ||
| 420 | } | ||
| 421 | } | ||
| 422 | |||
| 423 | fn capabilities(&self) -> embassy_net::DeviceCapabilities { | ||
| 424 | let mut caps = embassy_net::DeviceCapabilities::default(); | ||
| 425 | caps.max_transmission_unit = 1514; // 1500 IP + 14 ethernet header | ||
| 426 | caps.medium = embassy_net::Medium::Ethernet; | ||
| 427 | caps | ||
| 428 | } | ||
| 429 | |||
| 430 | fn is_transmit_ready(&mut self) -> bool { | ||
| 431 | true | ||
| 432 | } | ||
| 433 | |||
| 434 | fn transmit(&mut self, pkt: PacketBuf) { | ||
| 435 | if self.state.tx_channel.try_send(pkt).is_err() { | ||
| 436 | warn!("TX failed") | ||
| 437 | } | ||
| 438 | } | ||
| 439 | |||
| 440 | fn receive(&mut self) -> Option<PacketBuf> { | ||
| 441 | self.state.rx_channel.try_recv().ok() | ||
| 442 | } | ||
| 443 | |||
| 444 | fn ethernet_address(&self) -> [u8; 6] { | ||
| 445 | self.mac_addr | ||
| 446 | } | ||
| 447 | } | ||
| 448 | |||
| 449 | pub struct Runner<'a, PWR, SPI> { | 394 | pub struct Runner<'a, PWR, SPI> { |
| 395 | ch: ch::Runner<'a, MTU>, | ||
| 450 | bus: Bus<PWR, SPI>, | 396 | bus: Bus<PWR, SPI>, |
| 451 | 397 | ||
| 452 | state: &'a State, | 398 | ioctl_state: &'a Cell<IoctlState>, |
| 453 | ioctl_id: u16, | 399 | ioctl_id: u16, |
| 454 | sdpcm_seq: u8, | 400 | sdpcm_seq: u8, |
| 455 | sdpcm_seq_max: u8, | 401 | sdpcm_seq_max: u8, |
| @@ -466,21 +412,27 @@ struct LogState { | |||
| 466 | buf_count: usize, | 412 | buf_count: usize, |
| 467 | } | 413 | } |
| 468 | 414 | ||
| 415 | pub type NetDriver<'a> = ch::Device<'a, MTU>; | ||
| 416 | |||
| 469 | pub async fn new<'a, PWR, SPI>( | 417 | pub async fn new<'a, PWR, SPI>( |
| 470 | state: &'a State, | 418 | state: &'a mut State, |
| 471 | pwr: PWR, | 419 | pwr: PWR, |
| 472 | spi: SPI, | 420 | spi: SPI, |
| 473 | firmware: &[u8], | 421 | firmware: &[u8], |
| 474 | ) -> (Control<'a>, Runner<'a, PWR, SPI>) | 422 | ) -> (NetDriver<'a>, Control<'a>, Runner<'a, PWR, SPI>) |
| 475 | where | 423 | where |
| 476 | PWR: OutputPin, | 424 | PWR: OutputPin, |
| 477 | SPI: SpiDevice, | 425 | SPI: SpiDevice, |
| 478 | SPI::Bus: SpiBusRead<u32> + SpiBusWrite<u32>, | 426 | SPI::Bus: SpiBusRead<u32> + SpiBusWrite<u32>, |
| 479 | { | 427 | { |
| 428 | let (ch_runner, device) = ch::new(&mut state.ch, [0; 6]); | ||
| 429 | let state_ch = ch_runner.state_runner(); | ||
| 430 | |||
| 480 | let mut runner = Runner { | 431 | let mut runner = Runner { |
| 432 | ch: ch_runner, | ||
| 481 | bus: Bus::new(pwr, spi), | 433 | bus: Bus::new(pwr, spi), |
| 482 | 434 | ||
| 483 | state, | 435 | ioctl_state: &state.ioctl_state, |
| 484 | ioctl_id: 0, | 436 | ioctl_id: 0, |
| 485 | sdpcm_seq: 0, | 437 | sdpcm_seq: 0, |
| 486 | sdpcm_seq_max: 1, | 438 | sdpcm_seq_max: 1, |
| @@ -496,7 +448,14 @@ where | |||
| 496 | 448 | ||
| 497 | runner.init(firmware).await; | 449 | runner.init(firmware).await; |
| 498 | 450 | ||
| 499 | (Control { state }, runner) | 451 | ( |
| 452 | device, | ||
| 453 | Control { | ||
| 454 | state_ch, | ||
| 455 | ioctl_state: &state.ioctl_state, | ||
| 456 | }, | ||
| 457 | runner, | ||
| 458 | ) | ||
| 500 | } | 459 | } |
| 501 | 460 | ||
| 502 | impl<'a, PWR, SPI> Runner<'a, PWR, SPI> | 461 | impl<'a, PWR, SPI> Runner<'a, PWR, SPI> |
| @@ -662,15 +621,55 @@ where | |||
| 662 | if !self.has_credit() { | 621 | if !self.has_credit() { |
| 663 | warn!("TX stalled"); | 622 | warn!("TX stalled"); |
| 664 | } else { | 623 | } else { |
| 665 | if let IoctlState::Pending { kind, cmd, iface, buf } = self.state.ioctl_state.get() { | 624 | if let IoctlState::Pending { kind, cmd, iface, buf } = self.ioctl_state.get() { |
| 666 | self.send_ioctl(kind, cmd, iface, unsafe { &*buf }).await; | 625 | self.send_ioctl(kind, cmd, iface, unsafe { &*buf }).await; |
| 667 | self.state.ioctl_state.set(IoctlState::Sent { buf }); | 626 | self.ioctl_state.set(IoctlState::Sent { buf }); |
| 668 | } | 627 | } |
| 669 | if !self.has_credit() { | 628 | if !self.has_credit() { |
| 670 | warn!("TX stalled"); | 629 | warn!("TX stalled"); |
| 671 | } else { | 630 | } else { |
| 672 | if let Ok(p) = self.state.tx_channel.try_recv() { | 631 | if let Some(packet) = self.ch.try_tx_buf() { |
| 673 | self.send_packet(&p).await; | 632 | trace!("tx pkt {:02x}", &packet[..packet.len().min(48)]); |
| 633 | |||
| 634 | let mut buf = [0; 512]; | ||
| 635 | let buf8 = slice8_mut(&mut buf); | ||
| 636 | |||
| 637 | let total_len = SdpcmHeader::SIZE + BcdHeader::SIZE + packet.len(); | ||
| 638 | |||
| 639 | let seq = self.sdpcm_seq; | ||
| 640 | self.sdpcm_seq = self.sdpcm_seq.wrapping_add(1); | ||
| 641 | |||
| 642 | let sdpcm_header = SdpcmHeader { | ||
| 643 | len: total_len as u16, // TODO does this len need to be rounded up to u32? | ||
| 644 | len_inv: !total_len as u16, | ||
| 645 | sequence: seq, | ||
| 646 | channel_and_flags: CHANNEL_TYPE_DATA, | ||
| 647 | next_length: 0, | ||
| 648 | header_length: SdpcmHeader::SIZE as _, | ||
| 649 | wireless_flow_control: 0, | ||
| 650 | bus_data_credit: 0, | ||
| 651 | reserved: [0, 0], | ||
| 652 | }; | ||
| 653 | |||
| 654 | let bcd_header = BcdHeader { | ||
| 655 | flags: BDC_VERSION << BDC_VERSION_SHIFT, | ||
| 656 | priority: 0, | ||
| 657 | flags2: 0, | ||
| 658 | data_offset: 0, | ||
| 659 | }; | ||
| 660 | trace!("tx {:?}", sdpcm_header); | ||
| 661 | trace!(" {:?}", bcd_header); | ||
| 662 | |||
| 663 | buf8[0..SdpcmHeader::SIZE].copy_from_slice(&sdpcm_header.to_bytes()); | ||
| 664 | buf8[SdpcmHeader::SIZE..][..BcdHeader::SIZE].copy_from_slice(&bcd_header.to_bytes()); | ||
| 665 | buf8[SdpcmHeader::SIZE + BcdHeader::SIZE..][..packet.len()].copy_from_slice(packet); | ||
| 666 | |||
| 667 | let total_len = (total_len + 3) & !3; // round up to 4byte | ||
| 668 | |||
| 669 | trace!(" {:02x}", &buf8[..total_len.min(48)]); | ||
| 670 | |||
| 671 | self.bus.wlan_write(&buf[..(total_len / 4)]).await; | ||
| 672 | self.ch.tx_done(); | ||
| 674 | } | 673 | } |
| 675 | } | 674 | } |
| 676 | } | 675 | } |
| @@ -686,7 +685,6 @@ where | |||
| 686 | 685 | ||
| 687 | if status & STATUS_F2_PKT_AVAILABLE != 0 { | 686 | if status & STATUS_F2_PKT_AVAILABLE != 0 { |
| 688 | let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT; | 687 | let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT; |
| 689 | |||
| 690 | self.bus.wlan_read(&mut buf[..(len as usize + 3) / 4]).await; | 688 | self.bus.wlan_read(&mut buf[..(len as usize + 3) / 4]).await; |
| 691 | trace!("rx {:02x}", &slice8_mut(&mut buf)[..(len as usize).min(48)]); | 689 | trace!("rx {:02x}", &slice8_mut(&mut buf)[..(len as usize).min(48)]); |
| 692 | self.rx(&slice8_mut(&mut buf)[..len as usize]); | 690 | self.rx(&slice8_mut(&mut buf)[..len as usize]); |
| @@ -698,49 +696,6 @@ where | |||
| 698 | } | 696 | } |
| 699 | } | 697 | } |
| 700 | 698 | ||
| 701 | async fn send_packet(&mut self, packet: &[u8]) { | ||
| 702 | trace!("tx pkt {:02x}", &packet[..packet.len().min(48)]); | ||
| 703 | |||
| 704 | let mut buf = [0; 512]; | ||
| 705 | let buf8 = slice8_mut(&mut buf); | ||
| 706 | |||
| 707 | let total_len = SdpcmHeader::SIZE + BcdHeader::SIZE + packet.len(); | ||
| 708 | |||
| 709 | let seq = self.sdpcm_seq; | ||
| 710 | self.sdpcm_seq = self.sdpcm_seq.wrapping_add(1); | ||
| 711 | |||
| 712 | let sdpcm_header = SdpcmHeader { | ||
| 713 | len: total_len as u16, // TODO does this len need to be rounded up to u32? | ||
| 714 | len_inv: !total_len as u16, | ||
| 715 | sequence: seq, | ||
| 716 | channel_and_flags: CHANNEL_TYPE_DATA, | ||
| 717 | next_length: 0, | ||
| 718 | header_length: SdpcmHeader::SIZE as _, | ||
| 719 | wireless_flow_control: 0, | ||
| 720 | bus_data_credit: 0, | ||
| 721 | reserved: [0, 0], | ||
| 722 | }; | ||
| 723 | |||
| 724 | let bcd_header = BcdHeader { | ||
| 725 | flags: BDC_VERSION << BDC_VERSION_SHIFT, | ||
| 726 | priority: 0, | ||
| 727 | flags2: 0, | ||
| 728 | data_offset: 0, | ||
| 729 | }; | ||
| 730 | trace!("tx {:?}", sdpcm_header); | ||
| 731 | trace!(" {:?}", bcd_header); | ||
| 732 | |||
| 733 | buf8[0..SdpcmHeader::SIZE].copy_from_slice(&sdpcm_header.to_bytes()); | ||
| 734 | buf8[SdpcmHeader::SIZE..][..BcdHeader::SIZE].copy_from_slice(&bcd_header.to_bytes()); | ||
| 735 | buf8[SdpcmHeader::SIZE + BcdHeader::SIZE..][..packet.len()].copy_from_slice(packet); | ||
| 736 | |||
| 737 | let total_len = (total_len + 3) & !3; // round up to 4byte | ||
| 738 | |||
| 739 | trace!(" {:02x}", &buf8[..total_len.min(48)]); | ||
| 740 | |||
| 741 | self.bus.wlan_write(&buf[..(total_len / 4)]).await; | ||
| 742 | } | ||
| 743 | |||
| 744 | fn rx(&mut self, packet: &[u8]) { | 699 | fn rx(&mut self, packet: &[u8]) { |
| 745 | if packet.len() < SdpcmHeader::SIZE { | 700 | if packet.len() < SdpcmHeader::SIZE { |
| 746 | warn!("packet too short, len={}", packet.len()); | 701 | warn!("packet too short, len={}", packet.len()); |
| @@ -775,7 +730,7 @@ where | |||
| 775 | let cdc_header = CdcHeader::from_bytes(payload[..CdcHeader::SIZE].try_into().unwrap()); | 730 | let cdc_header = CdcHeader::from_bytes(payload[..CdcHeader::SIZE].try_into().unwrap()); |
| 776 | trace!(" {:?}", cdc_header); | 731 | trace!(" {:?}", cdc_header); |
| 777 | 732 | ||
| 778 | if let IoctlState::Sent { buf } = self.state.ioctl_state.get() { | 733 | if let IoctlState::Sent { buf } = self.ioctl_state.get() { |
| 779 | if cdc_header.id == self.ioctl_id { | 734 | if cdc_header.id == self.ioctl_id { |
| 780 | if cdc_header.status != 0 { | 735 | if cdc_header.status != 0 { |
| 781 | // TODO: propagate error instead | 736 | // TODO: propagate error instead |
| @@ -786,7 +741,7 @@ where | |||
| 786 | info!("IOCTL Response: {:02x}", &payload[CdcHeader::SIZE..][..resp_len]); | 741 | info!("IOCTL Response: {:02x}", &payload[CdcHeader::SIZE..][..resp_len]); |
| 787 | 742 | ||
| 788 | (unsafe { &mut *buf }[..resp_len]).copy_from_slice(&payload[CdcHeader::SIZE..][..resp_len]); | 743 | (unsafe { &mut *buf }[..resp_len]).copy_from_slice(&payload[CdcHeader::SIZE..][..resp_len]); |
| 789 | self.state.ioctl_state.set(IoctlState::Done { resp_len }); | 744 | self.ioctl_state.set(IoctlState::Done { resp_len }); |
| 790 | } | 745 | } |
| 791 | } | 746 | } |
| 792 | } | 747 | } |
| @@ -859,11 +814,12 @@ where | |||
| 859 | let packet = &payload[packet_start..]; | 814 | let packet = &payload[packet_start..]; |
| 860 | trace!("rx pkt {:02x}", &packet[..(packet.len() as usize).min(48)]); | 815 | trace!("rx pkt {:02x}", &packet[..(packet.len() as usize).min(48)]); |
| 861 | 816 | ||
| 862 | let mut p = unwrap!(embassy_net::PacketBox::new(embassy_net::Packet::new())); | 817 | match self.ch.try_rx_buf() { |
| 863 | p[..packet.len()].copy_from_slice(packet); | 818 | Some(buf) => { |
| 864 | 819 | buf[..packet.len()].copy_from_slice(packet); | |
| 865 | if let Err(_) = self.state.rx_channel.try_send(p.slice(0..packet.len())) { | 820 | self.ch.rx_done(packet.len()) |
| 866 | warn!("failed to push rxd packet to the channel.") | 821 | } |
| 822 | None => warn!("failed to push rxd packet to the channel."), | ||
| 867 | } | 823 | } |
| 868 | } | 824 | } |
| 869 | _ => {} | 825 | _ => {} |
