net-esp-hosted: enable heartbeats from esp32 to detect if it crashes.
This commit is contained in:
		| @@ -53,6 +53,9 @@ impl<'a> Control<'a> { | ||||
|         debug!("wait for init event..."); | ||||
|         self.shared.init_wait().await; | ||||
|  | ||||
|         debug!("set heartbeat"); | ||||
|         self.set_heartbeat(10).await?; | ||||
|  | ||||
|         debug!("set wifi mode"); | ||||
|         self.set_wifi_mode(WifiMode::Sta as _).await?; | ||||
|  | ||||
| @@ -83,6 +86,13 @@ impl<'a> Control<'a> { | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     /// duration in seconds, clamped to [10, 3600] | ||||
|     async fn set_heartbeat(&mut self, duration: u32) -> Result<(), Error> { | ||||
|         let req = proto::CtrlMsgReqConfigHeartbeat { enable: true, duration }; | ||||
|         ioctl!(self, ReqConfigHeartbeat, RespConfigHeartbeat, req, resp); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     async fn get_mac_addr(&mut self) -> Result<[u8; 6], Error> { | ||||
|         let req = proto::CtrlMsgReqGetMacAddress { | ||||
|             mode: WifiMode::Sta as _, | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| #![no_std] | ||||
|  | ||||
| use embassy_futures::select::{select3, Either3}; | ||||
| use embassy_futures::select::{select4, Either4}; | ||||
| use embassy_net_driver_channel as ch; | ||||
| use embassy_net_driver_channel::driver::LinkState; | ||||
| use embassy_time::{Duration, Instant, Timer}; | ||||
| use embedded_hal::digital::{InputPin, OutputPin}; | ||||
| use embedded_hal_async::digital::Wait; | ||||
| @@ -94,6 +95,7 @@ enum InterfaceType { | ||||
| } | ||||
|  | ||||
| const MAX_SPI_BUFFER_SIZE: usize = 1600; | ||||
| const HEARTBEAT_MAX_GAP: Duration = Duration::from_secs(20); | ||||
|  | ||||
| pub struct State { | ||||
|     shared: Shared, | ||||
| @@ -135,6 +137,7 @@ where | ||||
|         ready, | ||||
|         reset, | ||||
|         spi, | ||||
|         heartbeat_deadline: Instant::now() + HEARTBEAT_MAX_GAP, | ||||
|     }; | ||||
|     runner.init().await; | ||||
|  | ||||
| @@ -147,6 +150,7 @@ pub struct Runner<'a, SPI, IN, OUT> { | ||||
|     shared: &'a Shared, | ||||
|  | ||||
|     next_seq: u16, | ||||
|     heartbeat_deadline: Instant, | ||||
|  | ||||
|     spi: SPI, | ||||
|     handshake: IN, | ||||
| @@ -178,9 +182,10 @@ where | ||||
|             let ioctl = self.shared.ioctl_wait_pending(); | ||||
|             let tx = self.ch.tx_buf(); | ||||
|             let ev = async { self.ready.wait_for_high().await.unwrap() }; | ||||
|             let hb = Timer::at(self.heartbeat_deadline); | ||||
|  | ||||
|             match select3(ioctl, tx, ev).await { | ||||
|                 Either3::First(PendingIoctl { buf, req_len }) => { | ||||
|             match select4(ioctl, tx, ev, hb).await { | ||||
|                 Either4::First(PendingIoctl { buf, req_len }) => { | ||||
|                     tx_buf[12..24].copy_from_slice(b"\x01\x08\x00ctrlResp\x02"); | ||||
|                     tx_buf[24..26].copy_from_slice(&(req_len as u16).to_le_bytes()); | ||||
|                     tx_buf[26..][..req_len].copy_from_slice(&unsafe { &*buf }[..req_len]); | ||||
| @@ -199,7 +204,7 @@ where | ||||
|                     header.checksum = checksum(&tx_buf[..26 + req_len]); | ||||
|                     tx_buf[0..12].copy_from_slice(&header.to_bytes()); | ||||
|                 } | ||||
|                 Either3::Second(packet) => { | ||||
|                 Either4::Second(packet) => { | ||||
|                     tx_buf[12..][..packet.len()].copy_from_slice(packet); | ||||
|  | ||||
|                     let mut header = PayloadHeader { | ||||
| @@ -218,9 +223,12 @@ where | ||||
|  | ||||
|                     self.ch.tx_done(); | ||||
|                 } | ||||
|                 Either3::Third(()) => { | ||||
|                 Either4::Third(()) => { | ||||
|                     tx_buf[..PayloadHeader::SIZE].fill(0); | ||||
|                 } | ||||
|                 Either4::Fourth(()) => { | ||||
|                     panic!("heartbeat from esp32 stopped") | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if tx_buf[0] != 0 { | ||||
| @@ -309,7 +317,7 @@ where | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn handle_event(&self, data: &[u8]) { | ||||
|     fn handle_event(&mut self, data: &[u8]) { | ||||
|         let Ok(event) = noproto::read::<CtrlMsg>(data) else { | ||||
|             warn!("failed to parse event"); | ||||
|             return; | ||||
| @@ -324,6 +332,7 @@ where | ||||
|  | ||||
|         match payload { | ||||
|             CtrlMsgPayload::EventEspInit(_) => self.shared.init_done(), | ||||
|             CtrlMsgPayload::EventHeartbeat(_) => self.heartbeat_deadline = Instant::now() + HEARTBEAT_MAX_GAP, | ||||
|             CtrlMsgPayload::EventStationDisconnectFromAp(e) => { | ||||
|                 info!("disconnected, code {}", e.resp); | ||||
|                 self.state_ch.set_link_state(LinkState::Down); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user