From 60933e205729cfa7aa87f99ed12d57a8edafa396 Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 19 Jan 2021 13:03:27 +0800 Subject: [PATCH 01/19] enc424j600: initial commit squashed from @occheung 's commits (afdab5f1) cargo: include enc424j600 dependencies (39e0b55b) main: feature gate different eth device (e845f566) nal: implement enc424j600 variant (befe70a8) nal: fix unnecessary w5500 dependencies (20efdcc9) settings: override eeprom MAC (0d90470a) use cargo fmt (6e13f4f1) cargo: add w5500 as default (83380a99) cargo: simplify smoltcp dependency (83109c3d) settings/mac: remove redundant code (a3db62fe) mac: use smoltcp (15f09642) eth_cfg: split off from main (4ae6e827) nal: migrated to enc424j600 (e66d9165) phy_config: minor fix (38692170) clean up --- .github/workflows/ci.yml | 77 ++++++++++++++++++++-- Cargo.lock | 112 ++++++++++++++++++++++++++++++++ Cargo.toml | 15 +++++ src/enc424j600_config.rs | 112 ++++++++++++++++++++++++++++++++ src/main.rs | 75 ++++++++++++++++----- src/serial_terminal.rs | 2 +- src/settings/global_settings.rs | 16 ++++- 7 files changed, 387 insertions(+), 22 deletions(-) create mode 100644 src/enc424j600_config.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b5c04a68..9ec9be12 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,7 +43,7 @@ jobs: with: command: clippy - compile: + compile-w5500: runs-on: ubuntu-latest strategy: matrix: @@ -96,7 +96,66 @@ jobs: (${{ github.ref == 'refs/heads/master' }} || ${{ github.ref == 'refs/heads/develop' }}) with: - name: Firmware Images + name: Firmware Images (W5500) + path: | + target/*/release/booster + booster-release.bin + + compile-enc424j600: + runs-on: ubuntu-latest + strategy: + matrix: + toolchain: + - stable + - beta + steps: + - uses: actions/checkout@v2 + + - name: Install Rust ${{ matrix.toolchain }} + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.toolchain }} + target: thumbv7em-none-eabihf + override: true + components: llvm-tools-preview + + - name: Install Binutils + uses: actions-rs/cargo@v1 + with: + command: install + args: cargo-binutils + + - name: Style Check + uses: actions-rs/cargo@v1 + with: + command: check + args: --verbose + + - name: Build [Debug] + uses: actions-rs/cargo@v1 + with: + command: build + args: --no-default-features --features phy_enc424j600 + + - name: Build [Release] + uses: actions-rs/cargo@v1 + with: + command: build + args: --release --no-default-features --features phy_enc424j600 + + - name: Generate Release + uses: actions-rs/cargo@v1 + with: + command: objcopy + args: --release --verbose -- -O binary booster-release.bin + + - name: Upload Release + uses: actions/upload-artifact@v2 + if: ${{ matrix.toolchain == 'stable' }} && + (${{ github.ref == 'refs/heads/master' }} || + ${{ github.ref == 'refs/heads/develop' }}) + with: + name: Firmware Images (ENC424J600) path: | target/*/release/booster booster-release.bin @@ -111,13 +170,23 @@ jobs: toolchain: nightly target: thumbv7em-none-eabihf override: true - - name: cargo build+unstable + - name: cargo build+unstable+w5500 uses: actions-rs/cargo@v1 with: command: build args: --features unstable - - name: cargo build+release+unstable + - name: cargo build+release+unstable+w5500 uses: actions-rs/cargo@v1 with: command: build args: --release --features unstable + - name: cargo build+unstable+enc424j600 + uses: actions-rs/cargo@v1 + with: + command: build + args: --no-default-features --features "unstable phy_enc424j600" + - name: cargo build+release+unstable+enc424j600 + uses: actions-rs/cargo@v1 + with: + command: build + args: --release --no-default-features --features "unstable phy_enc424j600" diff --git a/Cargo.lock b/Cargo.lock index 9b0c28ae..59ebcb6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,6 +78,12 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + [[package]] name = "booster" version = "0.1.0" @@ -94,6 +100,7 @@ dependencies = [ "dac7571", "debounced-pin", "embedded-hal", + "enc424j600", "enum-iterator", "heapless", "log", @@ -107,6 +114,7 @@ dependencies = [ "serde", "serde-json-core", "shared-bus", + "smoltcp", "stm32f4xx-hal", "tca9548", "usb-device", @@ -267,6 +275,29 @@ dependencies = [ "no-std-net", ] +[[package]] +name = "embedded-time" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f85ab0d224a6c70f11426a9f04d5f26d250605b80df8fbed197e49d4454f58d7" +dependencies = [ + "num", +] + +[[package]] +name = "enc424j600" +version = "0.2.0" +source = "git+https://git.m-labs.hk/M-Labs/ENC424J600.git#b6d1b3828a3e0d8b0b3109141a21a2034be3d1cd" +dependencies = [ + "aligned", + "embedded-hal", + "embedded-nal", + "embedded-time", + "heapless", + "smoltcp", + "volatile-register", +] + [[package]] name = "enum-iterator" version = "0.6.0" @@ -392,6 +423,12 @@ dependencies = [ "utf8-ranges", ] +[[package]] +name = "managed" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75de51135344a4f8ed3cfe2720dc27736f7711989703a0b43aadf3753c55577" + [[package]] name = "max6639" version = "0.1.0" @@ -455,6 +492,69 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2178127478ae4ee9be7180bc9c3bffb6354dd7238400db567102f98c413a9f35" +[[package]] +name = "num" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" +dependencies = [ + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + [[package]] name = "num_enum" version = "0.5.1" @@ -610,6 +710,18 @@ dependencies = [ "embedded-hal", ] +[[package]] +name = "smoltcp" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab527c390c7e107f687bd92a886a083fde61b8cdc700b37f3d7e4346ffd8fae1" +dependencies = [ + "bitflags", + "byteorder", + "log", + "managed", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/Cargo.toml b/Cargo.toml index 66ecc22e..a9694224 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,18 @@ features = ["stm32f407", "rt", "usb_fs"] [dependencies.w5500] git = "https://github.com/quartiq/w5500" branch = "feature/tcp-nal" +optional = true + +[dependencies.enc424j600] +git = "https://git.m-labs.hk/M-Labs/ENC424J600.git" +features = [ "nal" ] +optional = true + +[dependencies.smoltcp] +version = "0.7.0" +default-features = false +features = [ "ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp" ] +optional = true [dependencies.ad5627] path = "ad5627" @@ -63,6 +75,9 @@ path = "tca9548" [features] unstable = [] +phy_enc424j600 = [ "enc424j600", "smoltcp" ] +phy_w5500 = [ "w5500" ] +default = [ "phy_w5500" ] [profile.release] codegen-units = 1 # better optimizations diff --git a/src/enc424j600_config.rs b/src/enc424j600_config.rs new file mode 100644 index 00000000..dde312df --- /dev/null +++ b/src/enc424j600_config.rs @@ -0,0 +1,112 @@ +use super::SPI; +use crate::BoosterSettings; +use crate::NetworkStack; +use cortex_m::peripheral::DWT; +use enc424j600::nal::time; +use stm32f4xx_hal as hal; + +/// Containers for smoltcp-related network configurations +pub struct NetStorage { + pub socket_storage: [Option>; 1], + pub ip_addrs: [smoltcp::wire::IpCidr; 1], + pub neighbor_cache: [Option<(smoltcp::wire::IpAddress, smoltcp::iface::Neighbor)>; 8], + pub routes_cache: [Option<(smoltcp::wire::IpCidr, smoltcp::iface::Route)>; 8], + pub tx_storage: [u8; 4096], + pub rx_storage: [u8; 1024], +} + +static mut NET_STORE: NetStorage = NetStorage { + // Placeholder for the real IP address, which is initialized at runtime. + ip_addrs: [smoltcp::wire::IpCidr::Ipv6( + smoltcp::wire::Ipv6Cidr::SOLICITED_NODE_PREFIX, + )], + neighbor_cache: [None; 8], + routes_cache: [None; 8], + socket_storage: [None; 1], + tx_storage: [0; 4096], + rx_storage: [0; 1024], +}; + +pub struct Clock; +impl time::Clock for Clock { + type T = u32; + const SCALING_FACTOR: time::fraction::Fraction = + ::new(1, 168_000_000); + + fn try_now(&self) -> Result, time::clock::Error> { + Ok(time::Instant::new(DWT::get_cycle_count())) + } +} + +type Ethernet = NetworkStack< + 'static, + SPI, + hal::gpio::gpioa::PA4>, + Clock, +>; +type EthSpiInterface = + enc424j600::SpiEth>, fn(u32)>; + +pub fn setup(mut enc424j600: EthSpiInterface, settings: &BoosterSettings) -> Ethernet { + use enc424j600::EthController; + use smoltcp as net; + + enc424j600.init_dev().expect("PHY initialization failed"); + enc424j600 + .write_mac_address(settings.mac().as_bytes()) + .unwrap(); + + // Init Rx/Tx buffers + enc424j600.init_rxbuf().unwrap(); + enc424j600.init_txbuf().unwrap(); + + let eth_iface = unsafe { + let device = enc424j600::smoltcp_phy::SmoltcpDevice::new(enc424j600); + + NET_STORE.ip_addrs[0] = { + let ip = settings.ip().octets(); + let subnet = settings.subnet().octets(); + net::wire::IpCidr::new( + net::wire::IpAddress::from(net::wire::Ipv4Address::from_bytes(&ip)), + net::wire::IpAddress::from(net::wire::Ipv4Address::from_bytes(&subnet)) + .to_prefix_len() + .unwrap(), + ) + }; + + let routes = { + let gateway = net::wire::Ipv4Address::from_bytes(&settings.gateway().octets()); + let mut routes = net::iface::Routes::new(&mut NET_STORE.routes_cache[..]); + routes.add_default_ipv4_route(gateway).unwrap(); + routes + }; + + let neighbor_cache = net::iface::NeighborCache::new(&mut NET_STORE.neighbor_cache[..]); + + net::iface::EthernetInterfaceBuilder::new(device) + .ethernet_addr(net::wire::EthernetAddress::from_bytes( + settings.mac().as_bytes(), + )) + .neighbor_cache(neighbor_cache) + .ip_addrs(&mut NET_STORE.ip_addrs[..]) + .routes(routes) + .finalize() + }; + + let socket_set = unsafe { + let mut sockets = net::socket::SocketSet::new(&mut NET_STORE.socket_storage[..]); + + let mut tcp_socket = { + let tx_buffer = net::socket::TcpSocketBuffer::new(&mut NET_STORE.tx_storage[..]); + let rx_buffer = net::socket::TcpSocketBuffer::new(&mut NET_STORE.rx_storage[..]); + + net::socket::TcpSocket::new(rx_buffer, tx_buffer) + }; + tcp_socket.set_keep_alive(Some(net::time::Duration::from_millis(1000))); + + let _handle = sockets.add(tcp_socket); + sockets + }; + + NetworkStack::new(eth_iface, socket_set, Clock {}) +} diff --git a/src/main.rs b/src/main.rs index 19f2e7f1..e068c852 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,13 @@ #![no_std] #![no_main] #![cfg_attr(feature = "unstable", feature(llvm_asm))] +#[cfg(not(any(feature = "phy_enc424j600", feature = "phy_w5500")))] +compile_error!( + "A least one PHY device must be enabled. Use a feature gate to + enable." +); +#[cfg(all(feature = "phy_enc424j600", feature = "phy_w5500"))] +compile_error!("Cannot enable multiple ethernet PHY devices."); #[macro_use] extern crate log; @@ -24,6 +31,8 @@ use usb_device::prelude::*; mod booster_channels; mod chassis_fans; mod delay; +#[cfg(feature = "phy_enc424j600")] +mod enc424j600_config; mod error; mod linear_transformation; mod logger; @@ -38,6 +47,10 @@ mod watchdog; use booster_channels::{BoosterChannels, Channel}; use chassis_fans::ChassisFans; use delay::AsmDelay; +#[cfg(feature = "phy_enc424j600")] +use enc424j600::nal::NetworkStack; +#[cfg(feature = "phy_enc424j600")] +use enc424j600_config::Clock; use error::Error; use logger::BufferedLog; use rf_channel::{AdcPin, AnalogPins as AdcPins, ChannelPins as RfChannelPins, ChannelState}; @@ -74,8 +87,16 @@ type SPI = hal::spi::Spi< ), >; +#[cfg(feature = "phy_w5500")] type Ethernet = w5500::Interface>, SPI>; +#[cfg(feature = "phy_enc424j600")] +type Ethernet = NetworkStack< + 'static, + SPI, + hal::gpio::gpioa::PA4>, + Clock, +>; type MqttClient = minimq::MqttClient; type I2cBusManager = mutex::AtomicCheckManager; @@ -369,7 +390,10 @@ const APP: () = { c.device.SPI1, (sck, miso, mosi), mode, + #[cfg(feature = "phy_w5500")] 1.mhz().into(), + #[cfg(feature = "phy_enc424j600")] + hal::time::Hertz(enc424j600::spi::interfaces::SPI_CLOCK_FREQ), clocks, ) }; @@ -380,24 +404,36 @@ const APP: () = { pin }; - let mut w5500 = w5500::W5500::new( - spi, - cs, - w5500::OnWakeOnLan::Ignore, - w5500::OnPingRequest::Respond, - w5500::ConnectionType::Ethernet, - w5500::ArpResponses::Cache, - ) - .unwrap(); + #[cfg(feature = "phy_w5500")] + { + let mut w5500 = w5500::W5500::new( + spi, + cs, + w5500::OnWakeOnLan::Ignore, + w5500::OnPingRequest::Respond, + w5500::ConnectionType::Ethernet, + w5500::ArpResponses::Cache, + ) + .unwrap(); - w5500.set_mac(settings.mac()).unwrap(); + w5500.set_mac(settings.mac()).unwrap(); - // Set default netmask and gateway. - w5500.set_gateway(settings.gateway()).unwrap(); - w5500.set_subnet(settings.subnet()).unwrap(); - w5500.set_ip(settings.ip()).unwrap(); + // Set default netmask and gateway. + w5500.set_gateway(settings.gateway()).unwrap(); + w5500.set_subnet(settings.subnet()).unwrap(); + w5500.set_ip(settings.ip()).unwrap(); - w5500::Interface::new(w5500) + w5500::Interface::new(w5500) + } + + #[cfg(feature = "phy_enc424j600")] + { + let delay_ns: fn(u32) -> () = + |time_ns| cortex_m::asm::delay(time_ns * 21 / 125 + 1); + let enc424j600 = enc424j600::SpiEth::new(spi, cs, delay_ns); + let interface = enc424j600_config::setup(enc424j600, &settings); + interface + } }; minimq::MqttClient::::new( @@ -442,7 +478,16 @@ const APP: () = { // Generate a device serial number from the MAC address. *USB_SERIAL = { let mut serial_string: String = String::new(); + + #[cfg(feature = "phy_w5500")] let octets = settings.mac().octets; + #[cfg(feature = "phy_enc424j600")] + let octets: [u8; 6] = { + let mut array = [0; 6]; + array.copy_from_slice(settings.mac().as_bytes()); + array + }; + write!( &mut serial_string, "{:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}", diff --git a/src/serial_terminal.rs b/src/serial_terminal.rs index 43a4ef65..aa52bc17 100644 --- a/src/serial_terminal.rs +++ b/src/serial_terminal.rs @@ -11,7 +11,7 @@ use logos::Logos; use usbd_serial::UsbError; use core::fmt::Write; -use w5500::Ipv4Addr; +use minimq::embedded_nal::Ipv4Addr; #[derive(Logos)] enum Token { diff --git a/src/settings/global_settings.rs b/src/settings/global_settings.rs index 73b59b49..a1c6807a 100644 --- a/src/settings/global_settings.rs +++ b/src/settings/global_settings.rs @@ -6,8 +6,14 @@ //! Proprietary and confidential. use crate::{Eeprom, Error}; use heapless::{consts, String}; +use minimq::embedded_nal::Ipv4Addr; use serde::{Deserialize, Serialize}; -use w5500::{Ipv4Addr, MacAddress}; + +#[cfg(feature = "phy_w5500")] +use w5500::MacAddress; + +#[cfg(feature = "phy_enc424j600")] +use smoltcp::wire::EthernetAddress as MacAddress; use super::{SemVersion, SinaraBoardId, SinaraConfiguration}; @@ -255,7 +261,13 @@ impl BoosterSettings { /// Get the Booster MAC address. pub fn mac(&self) -> MacAddress { - MacAddress::from_bytes(self.eui48) + #[cfg(feature = "phy_w5500")] + { + MacAddress::from_bytes(self.eui48) + } + + #[cfg(feature = "phy_enc424j600")] + MacAddress::from_bytes(&self.eui48) } /// Get the Booster IP address. From 6b82f966c446caa4fe42d06da87423e3afe0bb5a Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Wed, 16 Jun 2021 14:24:41 +0800 Subject: [PATCH 02/19] bump minimq to d2ec3e83 & adapt --- Cargo.lock | 50 ++++++++++++++++++++++++++++----------------- Cargo.toml | 1 + src/mqtt_control.rs | 8 +++++--- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 59ebcb6d..84e2190f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,12 +26,12 @@ dependencies = [ [[package]] name = "as-slice" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb4d1c23475b74e3672afa8c2be22040b8b7783ad9b461021144ed10a46bb0e6" +checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" dependencies = [ - "generic-array 0.12.3", - "generic-array 0.13.2", + "generic-array 0.12.4", + "generic-array 0.13.3", "generic-array 0.14.4", "stable_deref_trait", ] @@ -57,7 +57,7 @@ version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e6ffd9a6d04298eb55d5ac6d0fde48c2f991468b5ba8aa263fe2d1ea7288c0a" dependencies = [ - "generic-array 0.13.2", + "generic-array 0.13.3", ] [[package]] @@ -102,7 +102,7 @@ dependencies = [ "embedded-hal", "enc424j600", "enum-iterator", - "heapless", + "heapless 0.5.6", "log", "logos", "max6639", @@ -195,7 +195,7 @@ dependencies = [ "cortex-m", "cortex-m-rt", "cortex-m-rtic-macros", - "heapless", + "heapless 0.5.6", "rtic-core", "version_check", ] @@ -270,7 +270,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae46eb1b02de5a76d9d0ea21d657ff5b0ad2cc47f3a7723608227b1dd1b3eb18" dependencies = [ - "heapless", + "heapless 0.5.6", "nb 1.0.0", "no-std-net", ] @@ -293,7 +293,7 @@ dependencies = [ "embedded-hal", "embedded-nal", "embedded-time", - "heapless", + "heapless 0.5.6", "smoltcp", "volatile-register", ] @@ -326,18 +326,18 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "generic-array" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" dependencies = [ "typenum", ] [[package]] name = "generic-array" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd" +checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" dependencies = [ "typenum", ] @@ -374,12 +374,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74911a68a1658cfcfb61bc0ccfbd536e3b6e906f8c2f7883ee50157e3e2184f1" dependencies = [ "as-slice", - "generic-array 0.13.2", + "generic-array 0.13.3", "hash32", "serde", "stable_deref_trait", ] +[[package]] +name = "heapless" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634bd4d29cbf24424d0a4bfcbf80c6960129dc24424752a7d1d1390607023422" +dependencies = [ + "as-slice", + "generic-array 0.14.4", + "hash32", + "stable_deref_trait", +] + [[package]] name = "indexmap" version = "1.6.0" @@ -461,14 +473,14 @@ dependencies = [ [[package]] name = "minimq" -version = "0.1.0" -source = "git+https://github.com/quartiq/minimq#4a2b850b647b575d832122eeb2ffdeaa3677835a" +version = "0.2.0" +source = "git+https://github.com/quartiq/minimq?rev=d2ec3e8351fa403ea96defd98c0b4410cbaa18a4#d2ec3e8351fa403ea96defd98c0b4410cbaa18a4" dependencies = [ "bit_field", "embedded-nal", "enum-iterator", "generic-array 0.14.4", - "heapless", + "heapless 0.6.1", ] [[package]] @@ -582,7 +594,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3e3f5c2e9a91383c6594ec68aa2dfdfe19a3c86f34b088ba7203f2483d2682f" dependencies = [ - "heapless", + "heapless 0.5.6", "postcard-cobs", "serde", ] @@ -685,7 +697,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89fd6016a00149b485f66da701f76d909210d319040c97b6eff300f6e2ba2153" dependencies = [ - "heapless", + "heapless 0.5.6", "serde", ] diff --git a/Cargo.toml b/Cargo.toml index a9694224..4544802f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ crc-any = { version = "2.3.5", default-features = false } [dependencies.minimq] git = "https://github.com/quartiq/minimq" +rev = "d2ec3e8351fa403ea96defd98c0b4410cbaa18a4" [dependencies.stm32f4xx-hal] git = "https://github.com/stm32-rs/stm32f4xx-hal" diff --git a/src/mqtt_control.rs b/src/mqtt_control.rs index 2eed1d71..1beec73e 100644 --- a/src/mqtt_control.rs +++ b/src/mqtt_control.rs @@ -306,9 +306,11 @@ impl ControlState { }) { Ok(_) => {} - // Whenever MQTT disconnects, we will lose our pending subscriptions. We will need - // to re-establish them once we reconnect. - Err(minimq::Error::Disconnected) => self.subscribed = false, + // Whenever the MQTT broker stops maintaining the session, + // this MQTT client will reset the session, + // and we will lose our pending subscriptions. + // We will need to re-establish them once we reconnect. + Err(minimq::Error::SessionReset) => self.subscribed = false, Err(e) => error!("Unexpected error: {:?}", e), } From 8d205bbf90d95d4a6bf5533a9506e454c86e5d59 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Wed, 16 Jun 2021 14:26:22 +0800 Subject: [PATCH 03/19] enc424j600: use smoltcp-nal 0.1.0, disable enc424j600 nal --- Cargo.lock | 87 ++++++---------------------------------- Cargo.toml | 5 ++- src/enc424j600_config.rs | 28 ++----------- src/main.rs | 17 ++++---- 4 files changed, 26 insertions(+), 111 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84e2190f..e840e863 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -115,6 +115,7 @@ dependencies = [ "serde-json-core", "shared-bus", "smoltcp", + "smoltcp-nal", "stm32f4xx-hal", "tca9548", "usb-device", @@ -275,15 +276,6 @@ dependencies = [ "no-std-net", ] -[[package]] -name = "embedded-time" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f85ab0d224a6c70f11426a9f04d5f26d250605b80df8fbed197e49d4454f58d7" -dependencies = [ - "num", -] - [[package]] name = "enc424j600" version = "0.2.0" @@ -291,9 +283,6 @@ source = "git+https://git.m-labs.hk/M-Labs/ENC424J600.git#b6d1b3828a3e0d8b0b3109 dependencies = [ "aligned", "embedded-hal", - "embedded-nal", - "embedded-time", - "heapless 0.5.6", "smoltcp", "volatile-register", ] @@ -504,69 +493,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2178127478ae4ee9be7180bc9c3bffb6354dd7238400db567102f98c413a9f35" -[[package]] -name = "num" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" -dependencies = [ - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - [[package]] name = "num_enum" version = "0.5.1" @@ -734,6 +660,17 @@ dependencies = [ "managed", ] +[[package]] +name = "smoltcp-nal" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e5aeb4818706fd74c35917692008d29a5314483c8180300a582253718ce57a" +dependencies = [ + "embedded-nal", + "heapless 0.5.6", + "smoltcp", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/Cargo.toml b/Cargo.toml index 4544802f..0eb15aee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ shared-bus = { version = "0.2.0-alpha.1", features = ["cortex-m"] } usb-device = "0.2.6" postcard = "0.5.1" crc-any = { version = "2.3.5", default-features = false } +smoltcp-nal = { version = "0.1.0", optional = true } [dependencies.minimq] git = "https://github.com/quartiq/minimq" @@ -41,7 +42,7 @@ optional = true [dependencies.enc424j600] git = "https://git.m-labs.hk/M-Labs/ENC424J600.git" -features = [ "nal" ] +features = [ "smoltcp-phy" ] optional = true [dependencies.smoltcp] @@ -76,7 +77,7 @@ path = "tca9548" [features] unstable = [] -phy_enc424j600 = [ "enc424j600", "smoltcp" ] +phy_enc424j600 = [ "enc424j600", "smoltcp-nal" ] phy_w5500 = [ "w5500" ] default = [ "phy_w5500" ] diff --git a/src/enc424j600_config.rs b/src/enc424j600_config.rs index dde312df..972ef528 100644 --- a/src/enc424j600_config.rs +++ b/src/enc424j600_config.rs @@ -1,8 +1,5 @@ -use super::SPI; +use super::{Ethernet, SPI}; use crate::BoosterSettings; -use crate::NetworkStack; -use cortex_m::peripheral::DWT; -use enc424j600::nal::time; use stm32f4xx_hal as hal; /// Containers for smoltcp-related network configurations @@ -27,23 +24,6 @@ static mut NET_STORE: NetStorage = NetStorage { rx_storage: [0; 1024], }; -pub struct Clock; -impl time::Clock for Clock { - type T = u32; - const SCALING_FACTOR: time::fraction::Fraction = - ::new(1, 168_000_000); - - fn try_now(&self) -> Result, time::clock::Error> { - Ok(time::Instant::new(DWT::get_cycle_count())) - } -} - -type Ethernet = NetworkStack< - 'static, - SPI, - hal::gpio::gpioa::PA4>, - Clock, ->; type EthSpiInterface = enc424j600::SpiEth>, fn(u32)>; @@ -93,7 +73,7 @@ pub fn setup(mut enc424j600: EthSpiInterface, settings: &BoosterSettings) -> Eth .finalize() }; - let socket_set = unsafe { + let sockets = unsafe { let mut sockets = net::socket::SocketSet::new(&mut NET_STORE.socket_storage[..]); let mut tcp_socket = { @@ -104,9 +84,9 @@ pub fn setup(mut enc424j600: EthSpiInterface, settings: &BoosterSettings) -> Eth }; tcp_socket.set_keep_alive(Some(net::time::Duration::from_millis(1000))); - let _handle = sockets.add(tcp_socket); + sockets.add(tcp_socket); sockets }; - NetworkStack::new(eth_iface, socket_set, Clock {}) + Ethernet::new(eth_iface, sockets) } diff --git a/src/main.rs b/src/main.rs index e068c852..86480cbb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,15 +47,13 @@ mod watchdog; use booster_channels::{BoosterChannels, Channel}; use chassis_fans::ChassisFans; use delay::AsmDelay; -#[cfg(feature = "phy_enc424j600")] -use enc424j600::nal::NetworkStack; -#[cfg(feature = "phy_enc424j600")] -use enc424j600_config::Clock; use error::Error; use logger::BufferedLog; use rf_channel::{AdcPin, AnalogPins as AdcPins, ChannelPins as RfChannelPins, ChannelState}; use serial_terminal::SerialTerminal; use settings::BoosterSettings; +#[cfg(feature = "phy_enc424j600")] +use smoltcp_nal::NetworkStack; use user_interface::{ButtonEvent, Color, UserButtons, UserLeds}; use watchdog::{WatchdogClient, WatchdogManager}; @@ -91,12 +89,11 @@ type SPI = hal::spi::Spi< type Ethernet = w5500::Interface>, SPI>; #[cfg(feature = "phy_enc424j600")] -type Ethernet = NetworkStack< - 'static, - SPI, - hal::gpio::gpioa::PA4>, - Clock, ->; +type EthSpiInterface = + enc424j600::SpiEth>, fn(u32)>; +#[cfg(feature = "phy_enc424j600")] +type Ethernet = + NetworkStack<'static, 'static, enc424j600::smoltcp_phy::SmoltcpDevice>; type MqttClient = minimq::MqttClient; type I2cBusManager = mutex::AtomicCheckManager; From c27a6f7453be1c6ab7901911cc6f4088e851aa40 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Wed, 16 Jun 2021 14:30:04 +0800 Subject: [PATCH 04/19] enc424j600: bump enc424j600 to bb6824b9 & adapt * This also tells the ENC424J600 driver to use Cortex-M instructions to perform SPI CS_n delays at the current firmware CPU clock frequency. --- Cargo.lock | 40 +++++++++++++++++++++++++++++----------- Cargo.toml | 3 ++- src/enc424j600_config.rs | 24 +++++++++++------------- src/main.rs | 13 +++++-------- 4 files changed, 47 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e840e863..733c83ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,6 +15,12 @@ dependencies = [ "embedded-hal", ] +[[package]] +name = "aligned" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d39da9b88ae1a81c03c9c082b8db83f1d0e93914126041962af61034ab44c4a5" + [[package]] name = "aligned" version = "0.3.4" @@ -92,7 +98,7 @@ dependencies = [ "ads7924", "bbqueue", "bit_field", - "cortex-m", + "cortex-m 0.6.3", "cortex-m-log", "cortex-m-rt", "cortex-m-rtic", @@ -144,13 +150,25 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "cortex-m" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59971a5cf4dacacaf738dd9d8660875118fce790f800f661893eb20894c1d622" +dependencies = [ + "aligned 0.2.0", + "bare-metal", + "cortex-m 0.6.3", + "volatile-register", +] + [[package]] name = "cortex-m" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2be99930c99669a74d986f7fd2162085498b322e6daae8ef63a97cc9ac1dc73c" dependencies = [ - "aligned", + "aligned 0.3.4", "bare-metal", "bitfield", "volatile-register", @@ -162,7 +180,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d63959cb1e003dd97233fee6762351540253237eadf06fcdcb98cbfa3f9be4a" dependencies = [ - "cortex-m", + "cortex-m 0.6.3", "log", ] @@ -193,7 +211,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b30efcb6b7920d9016182c485687f0012487032a14c415d2fce6e9862ef8260e" dependencies = [ - "cortex-m", + "cortex-m 0.6.3", "cortex-m-rt", "cortex-m-rtic-macros", "heapless 0.5.6", @@ -279,9 +297,10 @@ dependencies = [ [[package]] name = "enc424j600" version = "0.2.0" -source = "git+https://git.m-labs.hk/M-Labs/ENC424J600.git#b6d1b3828a3e0d8b0b3109141a21a2034be3d1cd" +source = "git+https://git.m-labs.hk/M-Labs/ENC424J600.git?rev=bb6824b9447fda14a97ab277e05b760ca0959e6a#bb6824b9447fda14a97ab277e05b760ca0959e6a" dependencies = [ - "aligned", + "aligned 0.3.4", + "cortex-m 0.5.11", "embedded-hal", "smoltcp", "volatile-register", @@ -644,7 +663,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f42e140835229dea9c0b2498d2c88afe52ed2bd42a7cc6068c95adb5134b541" dependencies = [ - "cortex-m", + "cortex-m 0.6.3", "embedded-hal", ] @@ -656,7 +675,6 @@ checksum = "ab527c390c7e107f687bd92a886a083fde61b8cdc700b37f3d7e4346ffd8fae1" dependencies = [ "bitflags", "byteorder", - "log", "managed", ] @@ -684,7 +702,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11460b4de3a84f072e2cf6e76306c64d27f405a0e83bace0a726f555ddf4bf33" dependencies = [ "bare-metal", - "cortex-m", + "cortex-m 0.6.3", "cortex-m-rt", "vcell", ] @@ -696,7 +714,7 @@ source = "git+https://github.com/stm32-rs/stm32f4xx-hal#1dabe771eb141139ff1a2ead dependencies = [ "bare-metal", "cast", - "cortex-m", + "cortex-m 0.6.3", "cortex-m-rt", "embedded-dma", "embedded-hal", @@ -724,7 +742,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "461676dcf123675b3d3b02e2390e6a690cd186aacf2f439af7673c79e2561d53" dependencies = [ - "cortex-m", + "cortex-m 0.6.3", "usb-device", "vcell", ] diff --git a/Cargo.toml b/Cargo.toml index 0eb15aee..1230c8f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,8 @@ optional = true [dependencies.enc424j600] git = "https://git.m-labs.hk/M-Labs/ENC424J600.git" -features = [ "smoltcp-phy" ] +rev = "bb6824b9447fda14a97ab277e05b760ca0959e6a" +features = [ "smoltcp-phy", "cortex-m-cpu" ] optional = true [dependencies.smoltcp] diff --git a/src/enc424j600_config.rs b/src/enc424j600_config.rs index 972ef528..8f4d4e28 100644 --- a/src/enc424j600_config.rs +++ b/src/enc424j600_config.rs @@ -1,6 +1,6 @@ -use super::{Ethernet, SPI}; +use super::{Enc424j600, Ethernet}; use crate::BoosterSettings; -use stm32f4xx_hal as hal; +use embedded_hal::blocking::delay::DelayUs; /// Containers for smoltcp-related network configurations pub struct NetStorage { @@ -24,22 +24,20 @@ static mut NET_STORE: NetStorage = NetStorage { rx_storage: [0; 1024], }; -type EthSpiInterface = - enc424j600::SpiEth>, fn(u32)>; - -pub fn setup(mut enc424j600: EthSpiInterface, settings: &BoosterSettings) -> Ethernet { - use enc424j600::EthController; +pub fn setup( + mut enc424j600: Enc424j600, + settings: &BoosterSettings, + delay: &mut impl DelayUs, +) -> Ethernet { use smoltcp as net; - enc424j600.init_dev().expect("PHY initialization failed"); + enc424j600.init(delay).expect("PHY initialization failed"); + // Overriding the MAC address stored on ENC424J600 is currently for consistency; + // the value stored on the chip is currently unused for transmitting packets. enc424j600 - .write_mac_address(settings.mac().as_bytes()) + .write_mac_addr(settings.mac().as_bytes()) .unwrap(); - // Init Rx/Tx buffers - enc424j600.init_rxbuf().unwrap(); - enc424j600.init_txbuf().unwrap(); - let eth_iface = unsafe { let device = enc424j600::smoltcp_phy::SmoltcpDevice::new(enc424j600); diff --git a/src/main.rs b/src/main.rs index 86480cbb..7fa4f9c8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -89,11 +89,10 @@ type SPI = hal::spi::Spi< type Ethernet = w5500::Interface>, SPI>; #[cfg(feature = "phy_enc424j600")] -type EthSpiInterface = - enc424j600::SpiEth>, fn(u32)>; +type Enc424j600 = + enc424j600::Enc424j600>>; #[cfg(feature = "phy_enc424j600")] -type Ethernet = - NetworkStack<'static, 'static, enc424j600::smoltcp_phy::SmoltcpDevice>; +type Ethernet = NetworkStack<'static, 'static, enc424j600::smoltcp_phy::SmoltcpDevice>; type MqttClient = minimq::MqttClient; type I2cBusManager = mutex::AtomicCheckManager; @@ -425,10 +424,8 @@ const APP: () = { #[cfg(feature = "phy_enc424j600")] { - let delay_ns: fn(u32) -> () = - |time_ns| cortex_m::asm::delay(time_ns * 21 / 125 + 1); - let enc424j600 = enc424j600::SpiEth::new(spi, cs, delay_ns); - let interface = enc424j600_config::setup(enc424j600, &settings); + let enc424j600 = Enc424j600::new(spi, cs).cpu_freq_mhz(168); + let interface = enc424j600_config::setup(enc424j600, &settings, &mut delay); interface } }; From 5e298ad7cc1b0fcba670ddc51b9a7966a3fcb1ff Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Fri, 4 Jun 2021 14:24:13 +0800 Subject: [PATCH 05/19] switch to smoltcp-nal::smoltcp (0.7.0) --- Cargo.lock | 1 - Cargo.toml | 6 ------ src/enc424j600_config.rs | 1 + src/settings/global_settings.rs | 2 +- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 733c83ca..87694a77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,7 +120,6 @@ dependencies = [ "serde", "serde-json-core", "shared-bus", - "smoltcp", "smoltcp-nal", "stm32f4xx-hal", "tca9548", diff --git a/Cargo.toml b/Cargo.toml index 1230c8f9..3ca62ea4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,12 +46,6 @@ rev = "bb6824b9447fda14a97ab277e05b760ca0959e6a" features = [ "smoltcp-phy", "cortex-m-cpu" ] optional = true -[dependencies.smoltcp] -version = "0.7.0" -default-features = false -features = [ "ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp" ] -optional = true - [dependencies.ad5627] path = "ad5627" diff --git a/src/enc424j600_config.rs b/src/enc424j600_config.rs index 8f4d4e28..4c1af4fd 100644 --- a/src/enc424j600_config.rs +++ b/src/enc424j600_config.rs @@ -1,6 +1,7 @@ use super::{Enc424j600, Ethernet}; use crate::BoosterSettings; use embedded_hal::blocking::delay::DelayUs; +use smoltcp_nal::smoltcp; /// Containers for smoltcp-related network configurations pub struct NetStorage { diff --git a/src/settings/global_settings.rs b/src/settings/global_settings.rs index a1c6807a..d01ab54d 100644 --- a/src/settings/global_settings.rs +++ b/src/settings/global_settings.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; use w5500::MacAddress; #[cfg(feature = "phy_enc424j600")] -use smoltcp::wire::EthernetAddress as MacAddress; +use smoltcp_nal::smoltcp::wire::EthernetAddress as MacAddress; use super::{SemVersion, SinaraBoardId, SinaraConfiguration}; From f0a471be2fa6039d18b2e88ccd6d701491a385ed Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Wed, 16 Jun 2021 14:31:21 +0800 Subject: [PATCH 06/19] enc424j600: use cortex_m::singleton on NetStorage --- src/enc424j600_config.rs | 46 +++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/enc424j600_config.rs b/src/enc424j600_config.rs index 4c1af4fd..effcdcf1 100644 --- a/src/enc424j600_config.rs +++ b/src/enc424j600_config.rs @@ -13,17 +13,21 @@ pub struct NetStorage { pub rx_storage: [u8; 1024], } -static mut NET_STORE: NetStorage = NetStorage { - // Placeholder for the real IP address, which is initialized at runtime. - ip_addrs: [smoltcp::wire::IpCidr::Ipv6( - smoltcp::wire::Ipv6Cidr::SOLICITED_NODE_PREFIX, - )], - neighbor_cache: [None; 8], - routes_cache: [None; 8], - socket_storage: [None; 1], - tx_storage: [0; 4096], - rx_storage: [0; 1024], -}; +// Mutable reference to a singleton instance of NetStorage +fn net_store_as_mut() -> &'static mut NetStorage { + cortex_m::singleton!(: NetStorage = NetStorage { + // Placeholder for the real IP address, which is initialized at runtime. + ip_addrs: [smoltcp::wire::IpCidr::Ipv6( + smoltcp::wire::Ipv6Cidr::SOLICITED_NODE_PREFIX, + )], + neighbor_cache: [None; 8], + routes_cache: [None; 8], + socket_storage: [None; 1], + tx_storage: [0; 4096], + rx_storage: [0; 1024], + }) + .unwrap() +} pub fn setup( mut enc424j600: Enc424j600, @@ -39,10 +43,12 @@ pub fn setup( .write_mac_addr(settings.mac().as_bytes()) .unwrap(); - let eth_iface = unsafe { + let net_store = net_store_as_mut(); + + let eth_iface = { let device = enc424j600::smoltcp_phy::SmoltcpDevice::new(enc424j600); - NET_STORE.ip_addrs[0] = { + net_store.ip_addrs[0] = { let ip = settings.ip().octets(); let subnet = settings.subnet().octets(); net::wire::IpCidr::new( @@ -55,29 +61,29 @@ pub fn setup( let routes = { let gateway = net::wire::Ipv4Address::from_bytes(&settings.gateway().octets()); - let mut routes = net::iface::Routes::new(&mut NET_STORE.routes_cache[..]); + let mut routes = net::iface::Routes::new(&mut net_store.routes_cache[..]); routes.add_default_ipv4_route(gateway).unwrap(); routes }; - let neighbor_cache = net::iface::NeighborCache::new(&mut NET_STORE.neighbor_cache[..]); + let neighbor_cache = net::iface::NeighborCache::new(&mut net_store.neighbor_cache[..]); net::iface::EthernetInterfaceBuilder::new(device) .ethernet_addr(net::wire::EthernetAddress::from_bytes( settings.mac().as_bytes(), )) .neighbor_cache(neighbor_cache) - .ip_addrs(&mut NET_STORE.ip_addrs[..]) + .ip_addrs(&mut net_store.ip_addrs[..]) .routes(routes) .finalize() }; - let sockets = unsafe { - let mut sockets = net::socket::SocketSet::new(&mut NET_STORE.socket_storage[..]); + let sockets = { + let mut sockets = net::socket::SocketSet::new(&mut net_store.socket_storage[..]); let mut tcp_socket = { - let tx_buffer = net::socket::TcpSocketBuffer::new(&mut NET_STORE.tx_storage[..]); - let rx_buffer = net::socket::TcpSocketBuffer::new(&mut NET_STORE.rx_storage[..]); + let tx_buffer = net::socket::TcpSocketBuffer::new(&mut net_store.tx_storage[..]); + let rx_buffer = net::socket::TcpSocketBuffer::new(&mut net_store.rx_storage[..]); net::socket::TcpSocket::new(rx_buffer, tx_buffer) }; From 7b752040378d9fb1e7eb992ee14dfe7b3a4bdc45 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Mon, 7 Jun 2021 11:36:51 +0800 Subject: [PATCH 07/19] enc424j600: set SPI clock to max supported (14MHz) --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 7fa4f9c8..bab74f57 100644 --- a/src/main.rs +++ b/src/main.rs @@ -389,7 +389,7 @@ const APP: () = { #[cfg(feature = "phy_w5500")] 1.mhz().into(), #[cfg(feature = "phy_enc424j600")] - hal::time::Hertz(enc424j600::spi::interfaces::SPI_CLOCK_FREQ), + 14.mhz().into(), clocks, ) }; From 8639bc21051aca6b20fadfd87a1c123bd6fbf128 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Tue, 29 Jun 2021 11:43:50 +0800 Subject: [PATCH 08/19] enc424j600: introduce embedded_time-based clock --- Cargo.lock | 73 ++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 3 +- src/enc424j600_config.rs | 60 +++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 87694a77..387f6998 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,6 +106,7 @@ dependencies = [ "dac7571", "debounced-pin", "embedded-hal", + "embedded-time", "enc424j600", "enum-iterator", "heapless 0.5.6", @@ -293,6 +294,15 @@ dependencies = [ "no-std-net", ] +[[package]] +name = "embedded-time" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fbafcea0dea120d8ed8af67ddbf82afc031f1d3b064920645db8d061781e2c" +dependencies = [ + "num", +] + [[package]] name = "enc424j600" version = "0.2.0" @@ -511,6 +521,69 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2178127478ae4ee9be7180bc9c3bffb6354dd7238400db567102f98c413a9f35" +[[package]] +name = "num" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" +dependencies = [ + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + [[package]] name = "num_enum" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 3ca62ea4..69386496 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ usb-device = "0.2.6" postcard = "0.5.1" crc-any = { version = "2.3.5", default-features = false } smoltcp-nal = { version = "0.1.0", optional = true } +embedded-time = { version = "0.12.0", optional = true } [dependencies.minimq] git = "https://github.com/quartiq/minimq" @@ -72,7 +73,7 @@ path = "tca9548" [features] unstable = [] -phy_enc424j600 = [ "enc424j600", "smoltcp-nal" ] +phy_enc424j600 = [ "enc424j600", "smoltcp-nal", "embedded-time" ] phy_w5500 = [ "w5500" ] default = [ "phy_w5500" ] diff --git a/src/enc424j600_config.rs b/src/enc424j600_config.rs index effcdcf1..75628a2b 100644 --- a/src/enc424j600_config.rs +++ b/src/enc424j600_config.rs @@ -1,6 +1,8 @@ use super::{Enc424j600, Ethernet}; use crate::BoosterSettings; +use cortex_m::peripheral::DWT; use embedded_hal::blocking::delay::DelayUs; +use embedded_time::{clock, duration::*, Instant}; use smoltcp_nal::smoltcp; /// Containers for smoltcp-related network configurations @@ -95,3 +97,61 @@ pub fn setup( Ethernet::new(eth_iface, sockets) } + +#[derive(Debug)] +pub enum ClockError { + TimeFault, +} + +/// Simple struct for implementing embedded_time::Clock +pub struct EpochClock { + /// Epoch time in milliseconds to store a greater value + epoch_time_ms: Milliseconds, + /// Epoch time in ticks to store a temporary value + epoch_time_ticks: Instant, +} + +impl EpochClock { + pub fn new() -> Self { + Self { + epoch_time_ms: Milliseconds::::new(0), + epoch_time_ticks: Instant::::new(0), + } + } + + /// Update the valid epoch time in milliseconds, and returns the value. + /// + /// Safe to call after RTIC #[init]. Returns Err() if DWT CYCCNT returns a + /// smaller value than the last recorded time. + pub fn now(&mut self) -> Result { + use clock::Clock; + use core::convert::TryInto; + + let now = match self.try_now() { + Ok(now) => now, + Err(_) => return Err(ClockError::TimeFault), + }; + let elapsed: Milliseconds = match now.checked_duration_since(&self.epoch_time_ticks) { + Some(elapsed) => elapsed.try_into().map_err(|_| ClockError::TimeFault)?, + None => return Err(ClockError::TimeFault), + }; + self.epoch_time_ticks = now; + self.epoch_time_ms = self.epoch_time_ms + elapsed; + Ok(self.epoch_time_ms.integer()) + } +} + +/// Implement a simple embedded_time::clock::Clock at the given CPU clock frequency +/// based on DWT CYCCNT. +/// +/// This leverages "const generics" introduced in Rust 1.51. +impl clock::Clock for EpochClock { + type T = u32; + + const SCALING_FACTOR: Fraction = Fraction::new(1, CPUFREQ); + + /// Returns directly from DWT CYCCNT. Not guaranteed to be valid. + fn try_now(&self) -> Result, clock::Error> { + Ok(Instant::new(DWT::get_cycle_count())) + } +} From 448e46322b8a3ab928617c38cccac87ff10f9762 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Tue, 29 Jun 2021 11:57:35 +0800 Subject: [PATCH 09/19] enc424j600: rename mod from _config to _api --- src/{enc424j600_config.rs => enc424j600_api.rs} | 0 src/main.rs | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/{enc424j600_config.rs => enc424j600_api.rs} (100%) diff --git a/src/enc424j600_config.rs b/src/enc424j600_api.rs similarity index 100% rename from src/enc424j600_config.rs rename to src/enc424j600_api.rs diff --git a/src/main.rs b/src/main.rs index bab74f57..3955d4e8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,7 +32,7 @@ mod booster_channels; mod chassis_fans; mod delay; #[cfg(feature = "phy_enc424j600")] -mod enc424j600_config; +mod enc424j600_api; mod error; mod linear_transformation; mod logger; @@ -425,7 +425,7 @@ const APP: () = { #[cfg(feature = "phy_enc424j600")] { let enc424j600 = Enc424j600::new(spi, cs).cpu_freq_mhz(168); - let interface = enc424j600_config::setup(enc424j600, &settings, &mut delay); + let interface = enc424j600_api::setup(enc424j600, &settings, &mut delay); interface } }; From c709389870283b6f729140c9661a09780433a7c7 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Tue, 29 Jun 2021 12:37:42 +0800 Subject: [PATCH 10/19] use container for accessing MQTT client, and NAL clock for ENC424J600 --- src/main.rs | 143 +++++++++++++++++++++++++------------------- src/mqtt_control.rs | 83 +++++++++++++------------ 2 files changed, 125 insertions(+), 101 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3955d4e8..52d3fc6c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -93,6 +93,8 @@ type Enc424j600 = enc424j600::Enc424j600>>; #[cfg(feature = "phy_enc424j600")] type Ethernet = NetworkStack<'static, 'static, enc424j600::smoltcp_phy::SmoltcpDevice>; +#[cfg(feature = "phy_enc424j600")] +type NalClock = enc424j600_api::EpochClock<168_000_000>; type MqttClient = minimq::MqttClient; type I2cBusManager = mutex::AtomicCheckManager; @@ -166,6 +168,13 @@ pub struct MainBus { pub fans: ChassisFans, } +/// Container method for all Ethernet-related structs. +pub struct EthernetManager { + pub mqtt_client: MqttClient, + #[cfg(feature = "phy_enc424j600")] + pub nal_clock: NalClock, +} + #[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)] const APP: () = { struct Resources { @@ -173,7 +182,7 @@ const APP: () = { buttons: UserButtons, leds: UserLeds, usb_terminal: SerialTerminal, - mqtt_client: MqttClient, + eth_mgr: EthernetManager, watchdog: WatchdogManager, identifier: String, delay: AsmDelay, @@ -370,72 +379,80 @@ const APP: () = { let identifier: String = String::from(settings.id()); - let mqtt_client = { - let interface = { - let spi = { - let sck = gpioa.pa5.into_alternate_af5(); - let miso = gpioa.pa6.into_alternate_af5(); - let mosi = gpioa.pa7.into_alternate_af5(); + let eth_mgr = { + let mqtt_client = { + let interface = { + let spi = { + let sck = gpioa.pa5.into_alternate_af5(); + let miso = gpioa.pa6.into_alternate_af5(); + let mosi = gpioa.pa7.into_alternate_af5(); + + let mode = hal::spi::Mode { + polarity: hal::spi::Polarity::IdleLow, + phase: hal::spi::Phase::CaptureOnFirstTransition, + }; + + hal::spi::Spi::spi1( + c.device.SPI1, + (sck, miso, mosi), + mode, + #[cfg(feature = "phy_w5500")] + 1.mhz().into(), + #[cfg(feature = "phy_enc424j600")] + 14.mhz().into(), + clocks, + ) + }; - let mode = hal::spi::Mode { - polarity: hal::spi::Polarity::IdleLow, - phase: hal::spi::Phase::CaptureOnFirstTransition, + let cs = { + let mut pin = gpioa.pa4.into_push_pull_output(); + pin.set_high().unwrap(); + pin }; - hal::spi::Spi::spi1( - c.device.SPI1, - (sck, miso, mosi), - mode, - #[cfg(feature = "phy_w5500")] - 1.mhz().into(), - #[cfg(feature = "phy_enc424j600")] - 14.mhz().into(), - clocks, - ) - }; + #[cfg(feature = "phy_w5500")] + { + let mut w5500 = w5500::W5500::new( + spi, + cs, + w5500::OnWakeOnLan::Ignore, + w5500::OnPingRequest::Respond, + w5500::ConnectionType::Ethernet, + w5500::ArpResponses::Cache, + ) + .unwrap(); + + w5500.set_mac(settings.mac()).unwrap(); + + // Set default netmask and gateway. + w5500.set_gateway(settings.gateway()).unwrap(); + w5500.set_subnet(settings.subnet()).unwrap(); + w5500.set_ip(settings.ip()).unwrap(); + + w5500::Interface::new(w5500) + } - let cs = { - let mut pin = gpioa.pa4.into_push_pull_output(); - pin.set_high().unwrap(); - pin + #[cfg(feature = "phy_enc424j600")] + { + let enc424j600 = Enc424j600::new(spi, cs).cpu_freq_mhz(168); + let interface = enc424j600_api::setup(enc424j600, &settings, &mut delay); + interface + } }; - #[cfg(feature = "phy_w5500")] - { - let mut w5500 = w5500::W5500::new( - spi, - cs, - w5500::OnWakeOnLan::Ignore, - w5500::OnPingRequest::Respond, - w5500::ConnectionType::Ethernet, - w5500::ArpResponses::Cache, - ) - .unwrap(); - - w5500.set_mac(settings.mac()).unwrap(); - - // Set default netmask and gateway. - w5500.set_gateway(settings.gateway()).unwrap(); - w5500.set_subnet(settings.subnet()).unwrap(); - w5500.set_ip(settings.ip()).unwrap(); - - w5500::Interface::new(w5500) - } - - #[cfg(feature = "phy_enc424j600")] - { - let enc424j600 = Enc424j600::new(spi, cs).cpu_freq_mhz(168); - let interface = enc424j600_api::setup(enc424j600, &settings, &mut delay); - interface - } + minimq::MqttClient::::new( + minimq::embedded_nal::IpAddr::V4(settings.broker()), + settings.id(), + interface, + ) + .unwrap() }; - minimq::MqttClient::::new( - minimq::embedded_nal::IpAddr::V4(settings.broker()), - settings.id(), - interface, - ) - .unwrap() + EthernetManager { + mqtt_client, + #[cfg(feature = "phy_enc424j600")] + nal_clock: NalClock::new(), + } }; let mut fans = { @@ -524,7 +541,7 @@ const APP: () = { main_bus: MainBus { fans, channels }, buttons: buttons, leds: leds, - mqtt_client, + eth_mgr, usb_terminal, watchdog: watchdog_manager, identifier, @@ -628,7 +645,7 @@ const APP: () = { .unwrap(); } - #[task(priority = 1, schedule = [telemetry], resources=[main_bus, mqtt_client, watchdog, identifier])] + #[task(priority = 1, schedule = [telemetry], resources=[main_bus, eth_mgr, watchdog, identifier])] fn telemetry(mut c: telemetry::Context) { let id = &c.resources.identifier; @@ -653,7 +670,7 @@ const APP: () = { let message: String = serde_json_core::to_string(&measurements).unwrap(); - match c.resources.mqtt_client.publish( + match c.resources.eth_mgr.mqtt_client.publish( topic.as_str(), &message.into_bytes(), QoS::AtMostOnce, @@ -738,7 +755,7 @@ const APP: () = { .unwrap(); } - #[idle(resources=[main_bus, mqtt_client, watchdog, identifier, delay])] + #[idle(resources=[main_bus, eth_mgr, watchdog, identifier, delay])] fn idle(mut c: idle::Context) -> ! { let mut manager = c .resources diff --git a/src/mqtt_control.rs b/src/mqtt_control.rs index 1beec73e..f7ae5ddb 100644 --- a/src/mqtt_control.rs +++ b/src/mqtt_control.rs @@ -243,8 +243,8 @@ impl ControlState { use rtic::Mutex as _; // Subscribe to any control topics necessary. if !self.subscribed { - resources.mqtt_client.lock(|client| { - if client.is_connected().unwrap() { + resources.eth_mgr.lock(|eth_mgr| { + if eth_mgr.mqtt_client.is_connected().unwrap() { for topic in [ "channel/state", "channel/bias", @@ -253,7 +253,8 @@ impl ControlState { ] .iter() { - client + eth_mgr + .mqtt_client .subscribe(&self.generate_topic_string(topic), &[]) .unwrap(); } @@ -265,45 +266,51 @@ impl ControlState { let main_bus = &mut resources.main_bus; let delay = &mut resources.delay; - resources.mqtt_client.lock(|client| { - match client.poll(|client, topic, message, properties| { - let (id, route) = topic.split_at(topic.find('/').unwrap()); - let route = &route[1..]; - - if id != self.id { - warn!("Ignoring topic for identifier: {}", id); - return; - } + resources.eth_mgr.lock(|eth_mgr| { + match eth_mgr + .mqtt_client + .poll(|client, topic, message, properties| { + let (id, route) = topic.split_at(topic.find('/').unwrap()); + let route = &route[1..]; - let response = main_bus.lock(|main_bus| match route { - "channel/state" => handle_channel_update(message, &mut main_bus.channels), - "channel/bias" => handle_channel_bias(message, &mut main_bus.channels, *delay), - "channel/read" => handle_channel_property_read(message, &mut main_bus.channels), - "channel/write" => { - handle_channel_property_write(message, &mut main_bus.channels) + if id != self.id { + warn!("Ignoring topic for identifier: {}", id); + return; } - _ => Response::error_msg("Unexpected topic"), - }); - if let Property::ResponseTopic(topic) = properties - .iter() - .find(|&prop| { - if let Property::ResponseTopic(_) = *prop { - true - } else { - false + let response = main_bus.lock(|main_bus| match route { + "channel/state" => handle_channel_update(message, &mut main_bus.channels), + "channel/bias" => { + handle_channel_bias(message, &mut main_bus.channels, *delay) } - }) - .or(Some(&Property::ResponseTopic( - &self.generate_topic_string("log"), - ))) - .unwrap() - { - client - .publish(topic, &response.into_bytes(), QoS::AtMostOnce, &[]) - .unwrap(); - } - }) { + "channel/read" => { + handle_channel_property_read(message, &mut main_bus.channels) + } + "channel/write" => { + handle_channel_property_write(message, &mut main_bus.channels) + } + _ => Response::error_msg("Unexpected topic"), + }); + + if let Property::ResponseTopic(topic) = properties + .iter() + .find(|&prop| { + if let Property::ResponseTopic(_) = *prop { + true + } else { + false + } + }) + .or(Some(&Property::ResponseTopic( + &self.generate_topic_string("log"), + ))) + .unwrap() + { + client + .publish(topic, &response.into_bytes(), QoS::AtMostOnce, &[]) + .unwrap(); + } + }) { Ok(_) => {} // Whenever the MQTT broker stops maintaining the session, From 2f0b13064b8b45998023b55477dc026112fc68e4 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Tue, 29 Jun 2021 12:43:53 +0800 Subject: [PATCH 11/19] mqtt_control: implement smoltcp polling for ENC424J600 --- src/mqtt_control.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/mqtt_control.rs b/src/mqtt_control.rs index f7ae5ddb..db90410b 100644 --- a/src/mqtt_control.rs +++ b/src/mqtt_control.rs @@ -241,9 +241,21 @@ impl ControlState { /// * `resources` - The `idle` resources containing the client and RF channels. pub fn update(&mut self, resources: &mut Resources) { use rtic::Mutex as _; - // Subscribe to any control topics necessary. - if !self.subscribed { - resources.eth_mgr.lock(|eth_mgr| { + resources.eth_mgr.lock(|eth_mgr| { + // Update the NAL stack + #[cfg(feature = "phy_enc424j600")] + match eth_mgr.nal_clock.now() { + Ok(now) => { + // Note: smoltcp-nal 0.1.0 ONLY returns boolean, and does NOT + // raise errors from smoltcp. + // TODO: Bump smoltcp-nal + eth_mgr.mqtt_client.network_stack.poll(now); + } + Err(e) => error!("Network poll error: {:?}", e), + } + + // Subscribe to any control topics necessary. + if !self.subscribed { if eth_mgr.mqtt_client.is_connected().unwrap() { for topic in [ "channel/state", @@ -260,8 +272,8 @@ impl ControlState { } self.subscribed = true; } - }); - } + } + }); let main_bus = &mut resources.main_bus; let delay = &mut resources.delay; From c34501768cd06a7321ab61662b81d47871f0f879 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Tue, 29 Jun 2021 12:53:59 +0800 Subject: [PATCH 12/19] CI: control Eth PHY variants via matrix --- .github/workflows/ci.yml | 98 +++++++++------------------------------- 1 file changed, 22 insertions(+), 76 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ec9be12..e4e4f4bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,13 +43,19 @@ jobs: with: command: clippy - compile-w5500: + compile: runs-on: ubuntu-latest strategy: matrix: toolchain: - stable - beta + variant: [w5500, enc424j600] + include: + - variant: w5500 + cargo-args: '' + - variant: enc424j600 + cargo-args: --no-default-features --features phy_enc424j600 steps: - uses: actions/checkout@v2 @@ -77,18 +83,19 @@ jobs: uses: actions-rs/cargo@v1 with: command: build + args: ${{ matrix.cargo-args }} - name: Build [Release] uses: actions-rs/cargo@v1 with: command: build - args: --release + args: --release ${{ matrix.cargo-args }} - name: Generate Release uses: actions-rs/cargo@v1 with: command: objcopy - args: --release --verbose -- -O binary booster-release.bin + args: --release ${{ matrix.cargo-args }} --verbose -- -O binary booster-release.bin - name: Upload Release uses: actions/upload-artifact@v2 @@ -96,72 +103,21 @@ jobs: (${{ github.ref == 'refs/heads/master' }} || ${{ github.ref == 'refs/heads/develop' }}) with: - name: Firmware Images (W5500) + name: Firmware Images (${{ matrix.variant }}) path: | target/*/release/booster booster-release.bin - compile-enc424j600: + compile-unstable: runs-on: ubuntu-latest strategy: matrix: - toolchain: - - stable - - beta - steps: - - uses: actions/checkout@v2 - - - name: Install Rust ${{ matrix.toolchain }} - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ matrix.toolchain }} - target: thumbv7em-none-eabihf - override: true - components: llvm-tools-preview - - - name: Install Binutils - uses: actions-rs/cargo@v1 - with: - command: install - args: cargo-binutils - - - name: Style Check - uses: actions-rs/cargo@v1 - with: - command: check - args: --verbose - - - name: Build [Debug] - uses: actions-rs/cargo@v1 - with: - command: build - args: --no-default-features --features phy_enc424j600 - - - name: Build [Release] - uses: actions-rs/cargo@v1 - with: - command: build - args: --release --no-default-features --features phy_enc424j600 - - - name: Generate Release - uses: actions-rs/cargo@v1 - with: - command: objcopy - args: --release --verbose -- -O binary booster-release.bin - - - name: Upload Release - uses: actions/upload-artifact@v2 - if: ${{ matrix.toolchain == 'stable' }} && - (${{ github.ref == 'refs/heads/master' }} || - ${{ github.ref == 'refs/heads/develop' }}) - with: - name: Firmware Images (ENC424J600) - path: | - target/*/release/booster - booster-release.bin - - compile-unstable: - runs-on: ubuntu-latest + variant: [w5500, enc424j600] + include: + - variant: w5500 + cargo-args: '' + - variant: enc424j600 + cargo-args: --no-default-features --features phy_enc424j600 steps: - uses: actions/checkout@v2 - name: Install Rust Nightly @@ -170,23 +126,13 @@ jobs: toolchain: nightly target: thumbv7em-none-eabihf override: true - - name: cargo build+unstable+w5500 - uses: actions-rs/cargo@v1 - with: - command: build - args: --features unstable - - name: cargo build+release+unstable+w5500 - uses: actions-rs/cargo@v1 - with: - command: build - args: --release --features unstable - - name: cargo build+unstable+enc424j600 + - name: cargo build+unstable uses: actions-rs/cargo@v1 with: command: build - args: --no-default-features --features "unstable phy_enc424j600" - - name: cargo build+release+unstable+enc424j600 + args: --features unstable ${{ matrix.cargo-args }} + - name: cargo build+release+unstable uses: actions-rs/cargo@v1 with: command: build - args: --release --no-default-features --features "unstable phy_enc424j600" + args: --release --features unstable ${{ matrix.cargo-args }} From 88930f471fb7b59f313453db5d717a106faa3d68 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Thu, 26 Aug 2021 10:27:40 +0800 Subject: [PATCH 13/19] enc424j600: bump enc424j600 to fbcc3778 --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b4ece146..32f228e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -317,7 +317,7 @@ dependencies = [ [[package]] name = "enc424j600" version = "0.2.0" -source = "git+https://git.m-labs.hk/M-Labs/ENC424J600.git?rev=bb6824b9447fda14a97ab277e05b760ca0959e6a#bb6824b9447fda14a97ab277e05b760ca0959e6a" +source = "git+https://git.m-labs.hk/M-Labs/ENC424J600.git?rev=fbcc3778d27cfbeec7a1395c9b13a00c8a26af9a#fbcc3778d27cfbeec7a1395c9b13a00c8a26af9a" dependencies = [ "aligned 0.3.4", "cortex-m 0.5.11", diff --git a/Cargo.toml b/Cargo.toml index f09389d4..3b3b9852 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,7 @@ optional = true [dependencies.enc424j600] git = "https://git.m-labs.hk/M-Labs/ENC424J600.git" -rev = "bb6824b9447fda14a97ab277e05b760ca0959e6a" +rev = "fbcc3778d27cfbeec7a1395c9b13a00c8a26af9a" features = [ "smoltcp-phy", "cortex-m-cpu" ] optional = true From 5ca3f403c8e04372475a6111275f595b287f3063 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Thu, 2 Sep 2021 16:37:07 +0800 Subject: [PATCH 14/19] enc424j600_api: remove keep-alive --- src/enc424j600_api.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/enc424j600_api.rs b/src/enc424j600_api.rs index 75628a2b..cd93ea1d 100644 --- a/src/enc424j600_api.rs +++ b/src/enc424j600_api.rs @@ -83,13 +83,12 @@ pub fn setup( let sockets = { let mut sockets = net::socket::SocketSet::new(&mut net_store.socket_storage[..]); - let mut tcp_socket = { + let tcp_socket = { let tx_buffer = net::socket::TcpSocketBuffer::new(&mut net_store.tx_storage[..]); let rx_buffer = net::socket::TcpSocketBuffer::new(&mut net_store.rx_storage[..]); net::socket::TcpSocket::new(rx_buffer, tx_buffer) }; - tcp_socket.set_keep_alive(Some(net::time::Duration::from_millis(1000))); sockets.add(tcp_socket); sockets From e8bd495cfb498caeab77228c9c2e79eb958b4d94 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Mon, 27 Sep 2021 11:35:20 +0800 Subject: [PATCH 15/19] Define CPU clock frequency as const for consistency --- src/main.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main.rs b/src/main.rs index 727557d7..2c89ad88 100644 --- a/src/main.rs +++ b/src/main.rs @@ -61,6 +61,8 @@ use watchdog::{WatchdogClient, WatchdogManager}; use rtic::cyccnt::Duration; +const CPU_FREQ: u32 = 168_000_000; + // Convenience type definition for the I2C bus used for booster RF channels. type I2C = hal::i2c::I2c< hal::stm32::I2C1, @@ -96,7 +98,7 @@ type Enc424j600 = #[cfg(feature = "phy_enc424j600")] type Ethernet = NetworkStack<'static, 'static, enc424j600::smoltcp_phy::SmoltcpDevice>; #[cfg(feature = "phy_enc424j600")] -type NalClock = enc424j600_api::EpochClock<168_000_000>; +type NalClock = enc424j600_api::EpochClock; type MqttClient = minimq::MqttClient; type I2cBusManager = mutex::AtomicCheckManager; @@ -211,7 +213,7 @@ const APP: () = { .cfgr .use_hse(8.mhz()) .sysclk(168.mhz()) - .hclk(168.mhz()) + .hclk(CPU_FREQ.hz()) .pclk1(42.mhz()) .require_pll48clk() .freeze(); @@ -436,7 +438,8 @@ const APP: () = { #[cfg(feature = "phy_enc424j600")] { - let enc424j600 = Enc424j600::new(spi, cs).cpu_freq_mhz(168); + let enc424j600 = + Enc424j600::new(spi, cs).cpu_freq_mhz(CPU_FREQ / 1_000_000); let interface = enc424j600_api::setup(enc424j600, &settings, &mut delay); interface } @@ -606,7 +609,7 @@ const APP: () = { // TODO: Replace hard-coded CPU cycles here. // Schedule to run this task periodically at 10Hz. c.schedule - .channel_monitor(c.scheduled + Duration::from_cycles(168_000_000 / 10)) + .channel_monitor(c.scheduled + Duration::from_cycles(CPU_FREQ / 10)) .unwrap(); } @@ -640,7 +643,7 @@ const APP: () = { // TODO: Replace hard-coded CPU cycles here. // Schedule to run this task periodically at 1Hz. c.schedule - .fans(c.scheduled + Duration::from_cycles(168_000_000)) + .fans(c.scheduled + Duration::from_cycles(CPU_FREQ)) .unwrap(); } @@ -684,7 +687,7 @@ const APP: () = { // TODO: Replace hard-coded CPU cycles here. // Schedule to run this task periodically at 2Hz. c.schedule - .telemetry(c.scheduled + Duration::from_cycles(168_000_000 / 2)) + .telemetry(c.scheduled + Duration::from_cycles(CPU_FREQ / 2)) .unwrap(); } @@ -730,7 +733,7 @@ const APP: () = { // TODO: Replace hard-coded CPU cycles here. // Schedule to run this task every 3ms. c.schedule - .button(c.scheduled + Duration::from_cycles(3 * (168_000_000 / 1000))) + .button(c.scheduled + Duration::from_cycles(3 * (CPU_FREQ / 1000))) .unwrap(); } @@ -750,7 +753,7 @@ const APP: () = { // TODO: Replace hard-coded CPU cycles here. // Schedule to run this task every 10ms. c.schedule - .usb(c.scheduled + Duration::from_cycles(10 * (168_000_000 / 1_000))) + .usb(c.scheduled + Duration::from_cycles(10 * (CPU_FREQ / 1_000))) .unwrap(); } From 373f6b8a2bc99cf7dd6ffeb114bb165a13f2b76c Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Mon, 27 Sep 2021 11:25:32 +0800 Subject: [PATCH 16/19] enc424j600_api: additionally check for CPU clock consistency --- src/enc424j600_api.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/enc424j600_api.rs b/src/enc424j600_api.rs index cd93ea1d..3b6b5e00 100644 --- a/src/enc424j600_api.rs +++ b/src/enc424j600_api.rs @@ -112,6 +112,8 @@ pub struct EpochClock { impl EpochClock { pub fn new() -> Self { + assert!(CPUFREQ == crate::CPU_FREQ); + Self { epoch_time_ms: Milliseconds::::new(0), epoch_time_ticks: Instant::::new(0), From 80550905ea627e769405332847bb2a092ebf7e69 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Mon, 27 Sep 2021 12:09:43 +0800 Subject: [PATCH 17/19] CI: improve matrix for Eth PHY variants --- .github/workflows/ci.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4e4f4bf..dc8f94fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,9 +53,9 @@ jobs: variant: [w5500, enc424j600] include: - variant: w5500 - cargo-args: '' + variant-args: phy_w5500 - variant: enc424j600 - cargo-args: --no-default-features --features phy_enc424j600 + variant-args: phy_enc424j600 steps: - uses: actions/checkout@v2 @@ -83,19 +83,19 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: ${{ matrix.cargo-args }} + args: --no-default-features --features "${{ matrix.variant-args }}" - name: Build [Release] uses: actions-rs/cargo@v1 with: command: build - args: --release ${{ matrix.cargo-args }} + args: --release --no-default-features --features "${{ matrix.variant-args }}" - name: Generate Release uses: actions-rs/cargo@v1 with: command: objcopy - args: --release ${{ matrix.cargo-args }} --verbose -- -O binary booster-release.bin + args: --release --no-default-features --features "${{ matrix.variant-args }}" --verbose -- -O binary booster-release.bin - name: Upload Release uses: actions/upload-artifact@v2 @@ -115,9 +115,9 @@ jobs: variant: [w5500, enc424j600] include: - variant: w5500 - cargo-args: '' + variant-args: phy_w5500 - variant: enc424j600 - cargo-args: --no-default-features --features phy_enc424j600 + variant-args: phy_enc424j600 steps: - uses: actions/checkout@v2 - name: Install Rust Nightly @@ -130,9 +130,9 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --features unstable ${{ matrix.cargo-args }} + args: --no-default-features --features "unstable ${{ matrix.variant-args }}" - name: cargo build+release+unstable uses: actions-rs/cargo@v1 with: command: build - args: --release --features unstable ${{ matrix.cargo-args }} + args: --release --no-default-features --features "unstable ${{ matrix.variant-args }}" From 427a4a8d0932b7374202b04a95ce2f85a00fe1ee Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Tue, 28 Sep 2021 13:55:26 +0800 Subject: [PATCH 18/19] enc424j600_api: ignore errors due to tick overflow --- src/enc424j600_api.rs | 21 +++++++-------------- src/mqtt_control.rs | 14 ++++++-------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/enc424j600_api.rs b/src/enc424j600_api.rs index 3b6b5e00..0fa965a9 100644 --- a/src/enc424j600_api.rs +++ b/src/enc424j600_api.rs @@ -97,11 +97,6 @@ pub fn setup( Ethernet::new(eth_iface, sockets) } -#[derive(Debug)] -pub enum ClockError { - TimeFault, -} - /// Simple struct for implementing embedded_time::Clock pub struct EpochClock { /// Epoch time in milliseconds to store a greater value @@ -124,18 +119,16 @@ impl EpochClock { /// /// Safe to call after RTIC #[init]. Returns Err() if DWT CYCCNT returns a /// smaller value than the last recorded time. - pub fn now(&mut self) -> Result { + pub fn now(&mut self) -> Result { use clock::Clock; use core::convert::TryInto; - let now = match self.try_now() { - Ok(now) => now, - Err(_) => return Err(ClockError::TimeFault), - }; - let elapsed: Milliseconds = match now.checked_duration_since(&self.epoch_time_ticks) { - Some(elapsed) => elapsed.try_into().map_err(|_| ClockError::TimeFault)?, - None => return Err(ClockError::TimeFault), - }; + let now = self.try_now().unwrap(); + let elapsed: Milliseconds = now + .checked_duration_since(&self.epoch_time_ticks) + .unwrap() + .try_into() + .unwrap(); self.epoch_time_ticks = now; self.epoch_time_ms = self.epoch_time_ms + elapsed; Ok(self.epoch_time_ms.integer()) diff --git a/src/mqtt_control.rs b/src/mqtt_control.rs index 9be6c51f..f974ce18 100644 --- a/src/mqtt_control.rs +++ b/src/mqtt_control.rs @@ -244,14 +244,12 @@ impl ControlState { resources.eth_mgr.lock(|eth_mgr| { // Update the NAL stack #[cfg(feature = "phy_enc424j600")] - match eth_mgr.nal_clock.now() { - Ok(now) => { - // Note: smoltcp-nal 0.1.0 ONLY returns boolean, and does NOT - // raise errors from smoltcp. - // TODO: Bump smoltcp-nal - eth_mgr.mqtt_client.network_stack.poll(now); - } - Err(e) => error!("Network poll error: {:?}", e), + { + let now = eth_mgr.nal_clock.now().unwrap(); + // Note: smoltcp-nal 0.1.0 ONLY returns boolean, and does NOT + // raise errors from smoltcp. + // TODO: Bump smoltcp-nal + eth_mgr.mqtt_client.network_stack.poll(now); } // Subscribe to any control topics necessary. From 38fa6f4d1f5f2785c41ad1348ad68e37da1efb7c Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Tue, 28 Sep 2021 12:07:27 +0800 Subject: [PATCH 19/19] CI: simplify matrix for Eth variants --- .github/workflows/ci.yml | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc8f94fc..d229fad3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,12 +50,7 @@ jobs: toolchain: - stable - beta - variant: [w5500, enc424j600] - include: - - variant: w5500 - variant-args: phy_w5500 - - variant: enc424j600 - variant-args: phy_enc424j600 + variant: [phy_w5500, phy_enc424j600] steps: - uses: actions/checkout@v2 @@ -83,19 +78,19 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --no-default-features --features "${{ matrix.variant-args }}" + args: --no-default-features --features "${{ matrix.variant }}" - name: Build [Release] uses: actions-rs/cargo@v1 with: command: build - args: --release --no-default-features --features "${{ matrix.variant-args }}" + args: --release --no-default-features --features "${{ matrix.variant }}" - name: Generate Release uses: actions-rs/cargo@v1 with: command: objcopy - args: --release --no-default-features --features "${{ matrix.variant-args }}" --verbose -- -O binary booster-release.bin + args: --release --no-default-features --features "${{ matrix.variant }}" --verbose -- -O binary booster-release.bin - name: Upload Release uses: actions/upload-artifact@v2 @@ -103,7 +98,7 @@ jobs: (${{ github.ref == 'refs/heads/master' }} || ${{ github.ref == 'refs/heads/develop' }}) with: - name: Firmware Images (${{ matrix.variant }}) + name: Firmware Images (variant=${{ matrix.variant }}) path: | target/*/release/booster booster-release.bin @@ -112,12 +107,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - variant: [w5500, enc424j600] - include: - - variant: w5500 - variant-args: phy_w5500 - - variant: enc424j600 - variant-args: phy_enc424j600 + variant: [phy_w5500, phy_enc424j600] steps: - uses: actions/checkout@v2 - name: Install Rust Nightly @@ -130,9 +120,9 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --no-default-features --features "unstable ${{ matrix.variant-args }}" + args: --no-default-features --features "unstable ${{ matrix.variant }}" - name: cargo build+release+unstable uses: actions-rs/cargo@v1 with: command: build - args: --release --no-default-features --features "unstable ${{ matrix.variant-args }}" + args: --release --no-default-features --features "unstable ${{ matrix.variant }}"