diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-08-17 00:57:54 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-08-17 01:03:12 +0200 |
| commit | 1cb76e0d99f8da12891491b31176c8247a7a81a4 (patch) | |
| tree | b8a4e7f1969cb836cd52c2aa54f7e7b4d0371a90 | |
| parent | ef7523e5b7a36f0f15b77d4e673afdda0df51f3a (diff) | |
net-esp-hosted: enable heartbeats from esp32 to detect if it crashes.
| -rw-r--r-- | embassy-net-esp-hosted/src/control.rs | 10 | ||||
| -rw-r--r-- | embassy-net-esp-hosted/src/lib.rs | 21 |
2 files changed, 25 insertions, 6 deletions
diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs index b722bdd71..6cd57f68a 100644 --- a/embassy-net-esp-hosted/src/control.rs +++ b/embassy-net-esp-hosted/src/control.rs | |||
| @@ -53,6 +53,9 @@ impl<'a> Control<'a> { | |||
| 53 | debug!("wait for init event..."); | 53 | debug!("wait for init event..."); |
| 54 | self.shared.init_wait().await; | 54 | self.shared.init_wait().await; |
| 55 | 55 | ||
| 56 | debug!("set heartbeat"); | ||
| 57 | self.set_heartbeat(10).await?; | ||
| 58 | |||
| 56 | debug!("set wifi mode"); | 59 | debug!("set wifi mode"); |
| 57 | self.set_wifi_mode(WifiMode::Sta as _).await?; | 60 | self.set_wifi_mode(WifiMode::Sta as _).await?; |
| 58 | 61 | ||
| @@ -83,6 +86,13 @@ impl<'a> Control<'a> { | |||
| 83 | Ok(()) | 86 | Ok(()) |
| 84 | } | 87 | } |
| 85 | 88 | ||
| 89 | /// duration in seconds, clamped to [10, 3600] | ||
| 90 | async fn set_heartbeat(&mut self, duration: u32) -> Result<(), Error> { | ||
| 91 | let req = proto::CtrlMsgReqConfigHeartbeat { enable: true, duration }; | ||
| 92 | ioctl!(self, ReqConfigHeartbeat, RespConfigHeartbeat, req, resp); | ||
| 93 | Ok(()) | ||
| 94 | } | ||
| 95 | |||
| 86 | async fn get_mac_addr(&mut self) -> Result<[u8; 6], Error> { | 96 | async fn get_mac_addr(&mut self) -> Result<[u8; 6], Error> { |
| 87 | let req = proto::CtrlMsgReqGetMacAddress { | 97 | let req = proto::CtrlMsgReqGetMacAddress { |
| 88 | mode: WifiMode::Sta as _, | 98 | mode: WifiMode::Sta as _, |
diff --git a/embassy-net-esp-hosted/src/lib.rs b/embassy-net-esp-hosted/src/lib.rs index c2d9d6097..4a318b20d 100644 --- a/embassy-net-esp-hosted/src/lib.rs +++ b/embassy-net-esp-hosted/src/lib.rs | |||
| @@ -1,7 +1,8 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | 2 | ||
| 3 | use embassy_futures::select::{select3, Either3}; | 3 | use embassy_futures::select::{select4, Either4}; |
| 4 | use embassy_net_driver_channel as ch; | 4 | use embassy_net_driver_channel as ch; |
| 5 | use embassy_net_driver_channel::driver::LinkState; | ||
| 5 | use embassy_time::{Duration, Instant, Timer}; | 6 | use embassy_time::{Duration, Instant, Timer}; |
| 6 | use embedded_hal::digital::{InputPin, OutputPin}; | 7 | use embedded_hal::digital::{InputPin, OutputPin}; |
| 7 | use embedded_hal_async::digital::Wait; | 8 | use embedded_hal_async::digital::Wait; |
| @@ -94,6 +95,7 @@ enum InterfaceType { | |||
| 94 | } | 95 | } |
| 95 | 96 | ||
| 96 | const MAX_SPI_BUFFER_SIZE: usize = 1600; | 97 | const MAX_SPI_BUFFER_SIZE: usize = 1600; |
| 98 | const HEARTBEAT_MAX_GAP: Duration = Duration::from_secs(20); | ||
| 97 | 99 | ||
| 98 | pub struct State { | 100 | pub struct State { |
| 99 | shared: Shared, | 101 | shared: Shared, |
| @@ -135,6 +137,7 @@ where | |||
| 135 | ready, | 137 | ready, |
| 136 | reset, | 138 | reset, |
| 137 | spi, | 139 | spi, |
| 140 | heartbeat_deadline: Instant::now() + HEARTBEAT_MAX_GAP, | ||
| 138 | }; | 141 | }; |
| 139 | runner.init().await; | 142 | runner.init().await; |
| 140 | 143 | ||
| @@ -147,6 +150,7 @@ pub struct Runner<'a, SPI, IN, OUT> { | |||
| 147 | shared: &'a Shared, | 150 | shared: &'a Shared, |
| 148 | 151 | ||
| 149 | next_seq: u16, | 152 | next_seq: u16, |
| 153 | heartbeat_deadline: Instant, | ||
| 150 | 154 | ||
| 151 | spi: SPI, | 155 | spi: SPI, |
| 152 | handshake: IN, | 156 | handshake: IN, |
| @@ -178,9 +182,10 @@ where | |||
| 178 | let ioctl = self.shared.ioctl_wait_pending(); | 182 | let ioctl = self.shared.ioctl_wait_pending(); |
| 179 | let tx = self.ch.tx_buf(); | 183 | let tx = self.ch.tx_buf(); |
| 180 | let ev = async { self.ready.wait_for_high().await.unwrap() }; | 184 | let ev = async { self.ready.wait_for_high().await.unwrap() }; |
| 185 | let hb = Timer::at(self.heartbeat_deadline); | ||
| 181 | 186 | ||
| 182 | match select3(ioctl, tx, ev).await { | 187 | match select4(ioctl, tx, ev, hb).await { |
| 183 | Either3::First(PendingIoctl { buf, req_len }) => { | 188 | Either4::First(PendingIoctl { buf, req_len }) => { |
| 184 | tx_buf[12..24].copy_from_slice(b"\x01\x08\x00ctrlResp\x02"); | 189 | tx_buf[12..24].copy_from_slice(b"\x01\x08\x00ctrlResp\x02"); |
| 185 | tx_buf[24..26].copy_from_slice(&(req_len as u16).to_le_bytes()); | 190 | tx_buf[24..26].copy_from_slice(&(req_len as u16).to_le_bytes()); |
| 186 | tx_buf[26..][..req_len].copy_from_slice(&unsafe { &*buf }[..req_len]); | 191 | tx_buf[26..][..req_len].copy_from_slice(&unsafe { &*buf }[..req_len]); |
| @@ -199,7 +204,7 @@ where | |||
| 199 | header.checksum = checksum(&tx_buf[..26 + req_len]); | 204 | header.checksum = checksum(&tx_buf[..26 + req_len]); |
| 200 | tx_buf[0..12].copy_from_slice(&header.to_bytes()); | 205 | tx_buf[0..12].copy_from_slice(&header.to_bytes()); |
| 201 | } | 206 | } |
| 202 | Either3::Second(packet) => { | 207 | Either4::Second(packet) => { |
| 203 | tx_buf[12..][..packet.len()].copy_from_slice(packet); | 208 | tx_buf[12..][..packet.len()].copy_from_slice(packet); |
| 204 | 209 | ||
| 205 | let mut header = PayloadHeader { | 210 | let mut header = PayloadHeader { |
| @@ -218,9 +223,12 @@ where | |||
| 218 | 223 | ||
| 219 | self.ch.tx_done(); | 224 | self.ch.tx_done(); |
| 220 | } | 225 | } |
| 221 | Either3::Third(()) => { | 226 | Either4::Third(()) => { |
| 222 | tx_buf[..PayloadHeader::SIZE].fill(0); | 227 | tx_buf[..PayloadHeader::SIZE].fill(0); |
| 223 | } | 228 | } |
| 229 | Either4::Fourth(()) => { | ||
| 230 | panic!("heartbeat from esp32 stopped") | ||
| 231 | } | ||
| 224 | } | 232 | } |
| 225 | 233 | ||
| 226 | if tx_buf[0] != 0 { | 234 | if tx_buf[0] != 0 { |
| @@ -309,7 +317,7 @@ where | |||
| 309 | } | 317 | } |
| 310 | } | 318 | } |
| 311 | 319 | ||
| 312 | fn handle_event(&self, data: &[u8]) { | 320 | fn handle_event(&mut self, data: &[u8]) { |
| 313 | let Ok(event) = noproto::read::<CtrlMsg>(data) else { | 321 | let Ok(event) = noproto::read::<CtrlMsg>(data) else { |
| 314 | warn!("failed to parse event"); | 322 | warn!("failed to parse event"); |
| 315 | return; | 323 | return; |
| @@ -324,6 +332,7 @@ where | |||
| 324 | 332 | ||
| 325 | match payload { | 333 | match payload { |
| 326 | CtrlMsgPayload::EventEspInit(_) => self.shared.init_done(), | 334 | CtrlMsgPayload::EventEspInit(_) => self.shared.init_done(), |
| 335 | CtrlMsgPayload::EventHeartbeat(_) => self.heartbeat_deadline = Instant::now() + HEARTBEAT_MAX_GAP, | ||
| 327 | CtrlMsgPayload::EventStationDisconnectFromAp(e) => { | 336 | CtrlMsgPayload::EventStationDisconnectFromAp(e) => { |
| 328 | info!("disconnected, code {}", e.resp); | 337 | info!("disconnected, code {}", e.resp); |
| 329 | self.state_ch.set_link_state(LinkState::Down); | 338 | self.state_ch.set_link_state(LinkState::Down); |
