diff --git a/README.md b/README.md index 3923101..c77d0f1 100644 --- a/README.md +++ b/README.md @@ -9,44 +9,47 @@ Start nix shell before anything. nix-shell ``` -Flash firmware onto STM32 NUCLEO-H743ZI2 using OpenOCD. +**(For users who had completed the [networking setup](##networking-setup-for-first-time-user))** Flash firmware onto STM32 NUCLEO-H743ZI2 using OpenOCD. ```shell openocd -f openocd/openocd.cfg -f openocd/main.cfg ``` -Alternatively, an equivalent Nix command can also do the work +**(For users who had completed the [networking setup](##networking-setup-for-first-time-user))** Alternatively, an equivalent Nix command can also do the work. ```shell -openocd-flash main +openocd-flash ``` -## Networking Setup -At the moment, both IP addresses of the STM32 board and MQTT broker are hardcoded. -MAC address of the STM32 board is also hardcoded. +## Networking Setup for First-time User +Provide them to setup Humpback-DDS: +- IP Address of Humpback-DDS +- Address block of the local area network +- MAC Address of Humpback-DDS +- IP Address of MQTT broker +- Device name of Humpback-DDS -### STM32 IP Address -IP address is hardcoded in the file `src/main.rs`, line 171. -```rust -store.ip_addrs[0] = net::wire::IpCidr::new(net::wire::IpAddress::v4(192, 168, 1, 200), 24); -``` -The IP address shown above corresponds to `192.168.1.200`, in a `/24` address block. -Modify this line to the change the IP address of STM32 board. +Note: +- IP/MAC address of Humpback-DDS should be unique inside a local area network. +- Device name should be unique among all Humpback-DDS connected to the same MQTT broker. +- The MQTT broker must accept TCP connection at port `1883`. -### STM32 MAC Address -IP address is hardcoded in the file `src/main.rs`, line 156. -```rust -let mac_addr = net::wire::EthernetAddress([0xAC, 0x6F, 0x7A, 0xDE, 0xD6, 0xC8]); +Use the following Nix command. +```shell +openocd-flash-customised "" ``` -The MAC address shown above corresponds to `AC::6F::7A::DE::D6::C8`. -Modify this line to the change the MAC address of STM32 board. +Parameters: +- client_cidr_ip_addr: IP address for the Humpback-DDS device, in CIDR notation +- mac_addr: MAC address for the Humpback-DDS device +- broker_addr: IP address for the MQTT broker +- name: Device name of the Humpback-DDS -### Broker IP Address -IP address is hardcoded in the file `src/main.rs`, line 241. -```rust - IpAddr::V4(Ipv4Addr::new(192, 168, 1, 125)), +### Example +```shell +openocd-flash-customised 192.168.1.200/24 AC:6F:7A:DE:D6:C8 192.168.1.125 "Urukul" ``` -This program will try attempt to connect to `192.168.1.125:1883`. -Modify this line to the change the IP address of MQTT broker. -Note that the broker must accept TCP connection at `port 1883`. +The device will be named `Urukul`. +It has `192.168.1.200` as IPv4 Address, inside a `\24` network, with `AC:6F:7A:DE:D6:C8` as MAC address. +It will connect to a MQTT broker at `192.168.1.125:1883`. + ## MQTT Broker Mosquitto is within the Nix package. diff --git a/shell.nix b/shell.nix index 09abfda..b3bcbe7 100644 --- a/shell.nix +++ b/shell.nix @@ -1,41 +1,66 @@ let - mozillaOverlay = import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz); - pkgs = import {overlays = [mozillaOverlay];}; + mozillaOverlay = import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz); + pkgs = import {overlays = [mozillaOverlay];}; in with pkgs; let - migen = callPackage ./nix/migen.nix {}; - openocd = callPackage ./nix/openocd.nix {}; - rustPlatform = callPackage ./nix/rustPlatform.nix {}; - itm = callPackage ./nix/itm.nix {inherit rustPlatform;}; + migen = callPackage ./nix/migen.nix {}; + openocd = callPackage ./nix/openocd.nix {}; + rustPlatform = callPackage ./nix/rustPlatform.nix {}; + itm = callPackage ./nix/itm.nix {inherit rustPlatform;}; - runOpenOcdBlock = writeShellScriptBin "run-openocd-block" '' - openocd -f openocd/openocd.cfg - ''; + runOpenOcdBlock = writeShellScriptBin "run-openocd-block" '' + openocd -f openocd/openocd.cfg + ''; - openocdFlash = writeShellScriptBin "openocd-flash" '' - openocd -f openocd/openocd.cfg -f openocd/$1.cfg - ''; + openocdFlash = writeShellScriptBin "openocd-flash" '' + openocd -f openocd/openocd.cfg -f openocd/main.cfg + ''; - publishMqtt = writeShellScriptBin "publish-mqtt" '' - mosquitto_pub -h localhost -t $1 -m "$2" -d - ''; + publishMqtt = writeShellScriptBin "publish-mqtt" '' + mosquitto_pub -h localhost -t $1 -m "$2" -d + ''; + + openOCDFlashCustomised = writeShellScriptBin "openocd-flash-customised" '' + IFS='.|/' read -r a b c d e <<< $1 + ((ip = (a << 32) + (b << 24) + (c << 16) + (d << 8) + e)) + IFS=':' read -r a b c d e f <<< $2 + ((mac = (16#$a << 40) + (16#$b << 32) + (16#$c << 24) + (16#$d << 16) + (16#$e << 8) + 16#$f)) + IFS='.' read -r a b c d <<< $3 + ((broker_ip = (a << 24) + (b << 16) + (c << 8) + d)) + touch temp_name + printf "%s\x04" "$4" > temp_name + openocd -f openocd/openocd.cfg \ + -c "init + reset init + halt + stm32h7x mass_erase 1 + flash write_image erase target/thumbv7em-none-eabihf/release/humpback-dds + flash filld 0x08100000 $ip 1 + flash filld 0x08100020 $mac 1 + flash fillw 0x08100040 $broker_ip 1 + flash write_image temp_name 0x08100060 bin + reset run + shutdown" + rm temp_name + ''; in - stdenv.mkDerivation { - name = "Humpback-DDS"; - buildInputs = with rustPlatform.rust; [ - (pkgs.python3.withPackages(ps: [ migen ])) - pkgs.yosys - pkgs.nextpnr - pkgs.icestorm - pkgs.gdb - pkgs.mosquitto - openocd - rustc - cargo - itm - runOpenOcdBlock - openocdFlash - publishMqtt - ]; - } + stdenv.mkDerivation { + name = "Humpback-DDS"; + buildInputs = with rustPlatform.rust; [ + (pkgs.python3.withPackages(ps: [ migen ])) + pkgs.yosys + pkgs.nextpnr + pkgs.icestorm + pkgs.gdb + pkgs.mosquitto + openocd + rustc + cargo + itm + runOpenOcdBlock + openocdFlash + publishMqtt + openOCDFlashCustomised + ]; + } diff --git a/src/main.rs b/src/main.rs index 3ad6605..d79ded0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,8 @@ use rtic::cyccnt::{Instant, U32Ext}; use heapless::{ String, consts, consts::* }; +use core::convert::TryInto; + #[macro_use] pub mod bitmask_macro; pub mod spi_slave; @@ -110,6 +112,58 @@ fn main() -> ! { let gpiof = dp.GPIOF.split(ccdr.peripheral.GPIOF); let gpiog = dp.GPIOG.split(ccdr.peripheral.GPIOG); + // Acquire client/broker IP Address, client MAC address from flash memory + let ipv4_addr_cidr = unsafe { + let ipv4_bits = core::ptr::read(0x08100000 as *const u64); + net::wire::IpCidr::new( + net::wire::IpAddress::v4( + ((ipv4_bits >> 32) & 0xFF).try_into().unwrap(), + ((ipv4_bits >> 24) & 0xFF).try_into().unwrap(), + ((ipv4_bits >> 16) & 0xFF).try_into().unwrap(), + ((ipv4_bits >> 8) & 0xFF).try_into().unwrap() + ), + ((ipv4_bits >> 0) & 0xFF).try_into().unwrap() + ) + }; + + let mac_addr = unsafe { + let mac_bits = core::ptr::read(0x08100020 as *const u64); + net::wire::EthernetAddress([ + ((mac_bits >> 40) & 0xFF).try_into().unwrap(), + ((mac_bits >> 32) & 0xFF).try_into().unwrap(), + ((mac_bits >> 24) & 0xFF).try_into().unwrap(), + ((mac_bits >> 16) & 0xFF).try_into().unwrap(), + ((mac_bits >> 8) & 0xFF).try_into().unwrap(), + (mac_bits & 0xFF).try_into().unwrap(), + ]) + }; + + let broker_ipv4_addr = unsafe { + let ipv4_bits = core::ptr::read(0x08100040 as *const u64); + Ipv4Addr::new( + ((ipv4_bits >> 24) & 0xFF).try_into().unwrap(), + ((ipv4_bits >> 16) & 0xFF).try_into().unwrap(), + ((ipv4_bits >> 8) & 0xFF).try_into().unwrap(), + ((ipv4_bits >> 0) & 0xFF).try_into().unwrap() + ) + }; + + let device_name: String = unsafe { + let mut name = String::new(); + let mut addr = 0x08100060; + loop { + let c = core::ptr::read(addr as *const u8); + if c == 4 { + break; + } else { + name.push(c as char).unwrap(); + addr += 1; + } + } + name + }; + + // Note: ITM doesn't work beyond this, due to a pin conflict between: // - FPGA_SPI: SCK (af5) // - ST_LINK SWO (af0) @@ -153,7 +207,7 @@ fn main() -> ! { } // Configure ethernet - let mac_addr = net::wire::EthernetAddress([0xAC, 0x6F, 0x7A, 0xDE, 0xD6, 0xC8]); + // let mac_addr = net::wire::EthernetAddress([0xAC, 0x6F, 0x7A, 0xDE, 0xD6, 0xC8]); let (eth_dma, mut eth_mac) = unsafe { ethernet::new_unchecked( dp.ETHERNET_MAC, @@ -168,7 +222,7 @@ fn main() -> ! { let store = unsafe { &mut NET_STORE }; - store.ip_addrs[0] = net::wire::IpCidr::new(net::wire::IpAddress::v4(192, 168, 1, 200), 24); + store.ip_addrs[0] = ipv4_addr_cidr; let neighbor_cache = net::iface::NeighborCache::new(&mut store.neighbor_cache[..]); @@ -220,8 +274,7 @@ fn main() -> ! { ); urukul.reset().unwrap(); - let device_name = "Urukul"; - let mut mqtt_mux = MqttMux::new(urukul, device_name); + let mut mqtt_mux = MqttMux::new(urukul, device_name.as_str()); // Time unit in ms let mut time: u32 = 0; @@ -238,8 +291,8 @@ fn main() -> ! { let tcp_stack = NetworkStack::new(&mut net_interface, sockets); let mut client = MqttClient::::new( - IpAddr::V4(Ipv4Addr::new(192, 168, 1, 125)), - device_name, + IpAddr::V4(broker_ipv4_addr), + device_name.as_str(), tcp_stack, ) .unwrap(); @@ -286,7 +339,7 @@ fn main() -> ! { } if connection && !has_subscribed && tick { - let mut str_builder: String = String::from(device_name); + let mut str_builder: String = String::from(device_name.as_str()); str_builder.push_str("/Control/#").unwrap(); match client.subscribe(str_builder.as_str(), &[]) { Ok(()) => has_subscribed = true,