Merge branch 'master' into feature/livestream
This commit is contained in:
commit
2edbcf1c92
29
Cargo.lock
generated
29
Cargo.lock
generated
@ -145,18 +145,15 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "cortex-m-rt"
|
name = "cortex-m-rt"
|
||||||
version = "0.6.13"
|
version = "0.6.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/rust-embedded/cortex-m-rt.git?rev=a2e3ad5#a2e3ad54478c6b98e519a1b0946395d790c0b6c7"
|
||||||
checksum = "980c9d0233a909f355ed297ef122f257942de5e0a2cb1c39f60684b65bcb90fb"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cortex-m-rt-macros",
|
"cortex-m-rt-macros",
|
||||||
"r0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cortex-m-rt-macros"
|
name = "cortex-m-rt-macros"
|
||||||
version = "0.1.8"
|
version = "0.6.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/rust-embedded/cortex-m-rt.git?rev=a2e3ad5#a2e3ad54478c6b98e519a1b0946395d790c0b6c7"
|
||||||
checksum = "4717562afbba06e760d34451919f5c3bf3ac15c7bb897e8b04862a7428378647"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -203,7 +200,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_miniconf"
|
name = "derive_miniconf"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/quartiq/miniconf.git?rev=c6f2b28#c6f2b28f735e27b337eaa986846536e904c6f2bd"
|
source = "git+https://github.com/quartiq/miniconf.git?rev=2750533#275053396f0334e9efefa1ab2aae4c19b95a9a53"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -350,7 +347,6 @@ dependencies = [
|
|||||||
"as-slice",
|
"as-slice",
|
||||||
"generic-array 0.14.4",
|
"generic-array 0.14.4",
|
||||||
"hash32 0.1.1",
|
"hash32 0.1.1",
|
||||||
"serde",
|
|
||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -362,6 +358,7 @@ checksum = "c7ee8a997d259962217f40279f34201fdf06e669bafa69d7c1f4c7ff1893b5f6"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-polyfill",
|
"atomic-polyfill",
|
||||||
"hash32 0.2.1",
|
"hash32 0.2.1",
|
||||||
|
"serde",
|
||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -416,7 +413,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "miniconf"
|
name = "miniconf"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/quartiq/miniconf.git?rev=c6f2b28#c6f2b28f735e27b337eaa986846536e904c6f2bd"
|
source = "git+https://github.com/quartiq/miniconf.git?rev=2750533#275053396f0334e9efefa1ab2aae4c19b95a9a53"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"derive_miniconf",
|
"derive_miniconf",
|
||||||
"serde",
|
"serde",
|
||||||
@ -605,12 +602,6 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "r0"
|
|
||||||
version = "0.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.3"
|
version = "0.8.3"
|
||||||
@ -734,11 +725,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde-json-core"
|
name = "serde-json-core"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "39af17f40c2a28d2c9a7918663ddc8a10f54cc6f109ead5c3f010869761df186"
|
checksum = "8014aeea272bca0f0779778d43253f2f3375b414185b30e6ecc4d3e4a9994781"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heapless 0.6.1",
|
"heapless 0.7.1",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
@ -797,7 +788,7 @@ dependencies = [
|
|||||||
"cortex-m-rtic",
|
"cortex-m-rtic",
|
||||||
"dsp",
|
"dsp",
|
||||||
"embedded-hal",
|
"embedded-hal",
|
||||||
"heapless 0.6.1",
|
"heapless 0.7.1",
|
||||||
"log",
|
"log",
|
||||||
"mcp23017",
|
"mcp23017",
|
||||||
"miniconf",
|
"miniconf",
|
||||||
|
14
Cargo.toml
14
Cargo.toml
@ -33,7 +33,7 @@ cortex-m-rt = { version = "0.6", features = ["device"] }
|
|||||||
log = { version = "0.4", features = ["max_level_trace", "release_max_level_info"] }
|
log = { version = "0.4", features = ["max_level_trace", "release_max_level_info"] }
|
||||||
rtt-target = { version = "0.3", features = ["cortex-m"] }
|
rtt-target = { version = "0.3", features = ["cortex-m"] }
|
||||||
serde = { version = "1.0", features = ["derive"], default-features = false }
|
serde = { version = "1.0", features = ["derive"], default-features = false }
|
||||||
heapless = { version = "0.6", features = ["serde"] }
|
heapless = { version = "0.7", features = ["serde"] }
|
||||||
cortex-m-rtic = "0.5.6"
|
cortex-m-rtic = "0.5.6"
|
||||||
embedded-hal = "0.2.5"
|
embedded-hal = "0.2.5"
|
||||||
nb = "1.0.0"
|
nb = "1.0.0"
|
||||||
@ -44,13 +44,14 @@ dsp = { path = "dsp" }
|
|||||||
ad9959 = { path = "ad9959" }
|
ad9959 = { path = "ad9959" }
|
||||||
miniconf = "0.1.0"
|
miniconf = "0.1.0"
|
||||||
shared-bus = {version = "0.2.2", features = ["cortex-m"] }
|
shared-bus = {version = "0.2.2", features = ["cortex-m"] }
|
||||||
serde-json-core = "0.3"
|
serde-json-core = "0.4"
|
||||||
postcard = "0.6"
|
|
||||||
|
|
||||||
|
# rtt-target bump
|
||||||
[dependencies.rtt-logger]
|
[dependencies.rtt-logger]
|
||||||
git = "https://github.com/quartiq/rtt-logger.git"
|
git = "https://github.com/quartiq/rtt-logger.git"
|
||||||
rev = "70b0eb5"
|
rev = "70b0eb5"
|
||||||
|
|
||||||
|
# rewrite
|
||||||
[dependencies.mcp23017]
|
[dependencies.mcp23017]
|
||||||
git = "https://github.com/lucazulian/mcp23017.git"
|
git = "https://github.com/lucazulian/mcp23017.git"
|
||||||
rev = "523d71d"
|
rev = "523d71d"
|
||||||
@ -59,9 +60,14 @@ rev = "523d71d"
|
|||||||
features = ["stm32h743v", "rt", "unproven", "ethernet", "quadspi"]
|
features = ["stm32h743v", "rt", "unproven", "ethernet", "quadspi"]
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
|
||||||
|
# link.x section start/end
|
||||||
|
[patch.crates-io.cortex-m-rt]
|
||||||
|
git = "https://github.com/rust-embedded/cortex-m-rt.git"
|
||||||
|
rev = "a2e3ad5"
|
||||||
|
|
||||||
[patch.crates-io.miniconf]
|
[patch.crates-io.miniconf]
|
||||||
git = "https://github.com/quartiq/miniconf.git"
|
git = "https://github.com/quartiq/miniconf.git"
|
||||||
rev = "c6f2b28"
|
rev = "2750533"
|
||||||
|
|
||||||
[dependencies.smoltcp-nal]
|
[dependencies.smoltcp-nal]
|
||||||
git = "https://github.com/quartiq/smoltcp-nal.git"
|
git = "https://github.com/quartiq/smoltcp-nal.git"
|
||||||
|
3
build.rs
Normal file
3
build.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=memory.x");
|
||||||
|
}
|
20
memory.x
20
memory.x
@ -13,10 +13,6 @@ MEMORY
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
.itcm : ALIGN(8) {
|
|
||||||
*(.itcm .itcm.*);
|
|
||||||
. = ALIGN(8);
|
|
||||||
} > ITCM
|
|
||||||
.axisram (NOLOAD) : ALIGN(8) {
|
.axisram (NOLOAD) : ALIGN(8) {
|
||||||
*(.axisram .axisram.*);
|
*(.axisram .axisram.*);
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
@ -33,4 +29,18 @@ SECTIONS {
|
|||||||
*(.sram3 .sram3.*);
|
*(.sram3 .sram3.*);
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} > SRAM3
|
} > SRAM3
|
||||||
} INSERT AFTER .bss;
|
.itcm : ALIGN(8) {
|
||||||
|
. = ALIGN(8);
|
||||||
|
__sitcm = .;
|
||||||
|
*(.itcm .itcm.*);
|
||||||
|
. = ALIGN(8);
|
||||||
|
__eitcm = .;
|
||||||
|
} > ITCM AT>FLASH
|
||||||
|
__siitcm = LOADADDR(.itcm);
|
||||||
|
} INSERT AFTER .uninit;
|
||||||
|
|
||||||
|
ASSERT(__sitcm % 8 == 0 && __eitcm % 8 == 0, "
|
||||||
|
BUG(cortex-m-rt): .itcm is not 8-byte aligned");
|
||||||
|
|
||||||
|
ASSERT(__siitcm % 4 == 0, "
|
||||||
|
BUG(cortex-m-rt): the LMA of .itcm is not 4-byte aligned");
|
||||||
|
@ -129,6 +129,8 @@ const APP: () = {
|
|||||||
/// Because the ADC and DAC operate at the same rate, these two constraints actually implement
|
/// Because the ADC and DAC operate at the same rate, these two constraints actually implement
|
||||||
/// the same time bounds, meeting one also means the other is also met.
|
/// the same time bounds, meeting one also means the other is also met.
|
||||||
#[task(binds=DMA1_STR4, resources=[adcs, digital_inputs, dacs, iir_state, settings, telemetry, generator], priority=2)]
|
#[task(binds=DMA1_STR4, resources=[adcs, digital_inputs, dacs, iir_state, settings, telemetry, generator], priority=2)]
|
||||||
|
#[inline(never)]
|
||||||
|
#[link_section = ".itcm.process"]
|
||||||
fn process(c: process::Context) {
|
fn process(c: process::Context) {
|
||||||
let adc_samples = [
|
let adc_samples = [
|
||||||
c.resources.adcs.0.acquire_buffer(),
|
c.resources.adcs.0.acquire_buffer(),
|
||||||
|
@ -157,6 +157,8 @@ const APP: () = {
|
|||||||
/// It outputs either I/Q or power/phase on DAC0/DAC1. Data is normalized to full scale.
|
/// It outputs either I/Q or power/phase on DAC0/DAC1. Data is normalized to full scale.
|
||||||
/// PLL bandwidth, filter bandwidth, slope, and x/y or power/phase post-filters are available.
|
/// PLL bandwidth, filter bandwidth, slope, and x/y or power/phase post-filters are available.
|
||||||
#[task(binds=DMA1_STR4, resources=[adcs, dacs, lockin, timestamper, pll, settings, telemetry], priority=2)]
|
#[task(binds=DMA1_STR4, resources=[adcs, dacs, lockin, timestamper, pll, settings, telemetry], priority=2)]
|
||||||
|
#[inline(never)]
|
||||||
|
#[link_section = ".itcm.process"]
|
||||||
fn process(c: process::Context) {
|
fn process(c: process::Context) {
|
||||||
let adc_samples = [
|
let adc_samples = [
|
||||||
c.resources.adcs.0.acquire_buffer(),
|
c.resources.adcs.0.acquire_buffer(),
|
||||||
|
@ -126,6 +126,52 @@ pub struct PounderDevices {
|
|||||||
/// Static storage for the ethernet DMA descriptor ring.
|
/// Static storage for the ethernet DMA descriptor ring.
|
||||||
static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new();
|
static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new();
|
||||||
|
|
||||||
|
/// Setup ITCM and load its code from flash.
|
||||||
|
///
|
||||||
|
/// For portability and maintainability this is implemented in Rust.
|
||||||
|
/// Since this is implemented in Rust the compiler may assume that bss and data are set
|
||||||
|
/// up already. There is no easy way to ensure this implementation will never need bss
|
||||||
|
/// or data. Hence we can't safely run this as the cortex-m-rt `pre_init` hook before
|
||||||
|
/// bss/data is setup.
|
||||||
|
///
|
||||||
|
/// Calling (through IRQ or directly) any code in ITCM before having called
|
||||||
|
/// this method is undefined.
|
||||||
|
fn load_itcm() {
|
||||||
|
extern "C" {
|
||||||
|
static mut __sitcm: u32;
|
||||||
|
static mut __eitcm: u32;
|
||||||
|
static mut __siitcm: u32;
|
||||||
|
}
|
||||||
|
use core::{ptr, slice, sync::atomic};
|
||||||
|
|
||||||
|
// NOTE(unsafe): Assuming the address symbols from the linker as well as
|
||||||
|
// the source instruction data are all valid, this is safe as it only
|
||||||
|
// copies linker-prepared data to where the code expects it to be.
|
||||||
|
// Calling it multiple times is safe as well.
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
// ITCM is enabled on reset on our CPU but might not be on others.
|
||||||
|
// Keep for completeness.
|
||||||
|
const ITCMCR: *mut u32 = 0xE000_EF90usize as _;
|
||||||
|
ptr::write_volatile(ITCMCR, ptr::read_volatile(ITCMCR) | 1);
|
||||||
|
|
||||||
|
// Ensure ITCM is enabled before loading.
|
||||||
|
atomic::fence(atomic::Ordering::SeqCst);
|
||||||
|
|
||||||
|
let len =
|
||||||
|
(&__eitcm as *const u32).offset_from(&__sitcm as *const _) as usize;
|
||||||
|
let dst = slice::from_raw_parts_mut(&mut __sitcm as *mut _, len);
|
||||||
|
let src = slice::from_raw_parts(&__siitcm as *const _, len);
|
||||||
|
// Load code into ITCM.
|
||||||
|
dst.copy_from_slice(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure ITCM is loaded before potentially executing any instructions from it.
|
||||||
|
atomic::fence(atomic::Ordering::SeqCst);
|
||||||
|
cortex_m::asm::dsb();
|
||||||
|
cortex_m::asm::isb();
|
||||||
|
}
|
||||||
|
|
||||||
/// Configure the stabilizer hardware for operation.
|
/// Configure the stabilizer hardware for operation.
|
||||||
///
|
///
|
||||||
/// # Args
|
/// # Args
|
||||||
@ -178,9 +224,12 @@ pub fn setup(
|
|||||||
log::set_logger(&LOGGER)
|
log::set_logger(&LOGGER)
|
||||||
.map(|()| log::set_max_level(log::LevelFilter::Trace))
|
.map(|()| log::set_max_level(log::LevelFilter::Trace))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
log::info!("starting...");
|
log::info!("Starting");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Before being able to call any code in ITCM, load that code from flash.
|
||||||
|
load_itcm();
|
||||||
|
|
||||||
// Set up the system timer for RTIC scheduling.
|
// Set up the system timer for RTIC scheduling.
|
||||||
{
|
{
|
||||||
let tim15 =
|
let tim15 =
|
||||||
@ -906,6 +955,7 @@ pub fn setup(
|
|||||||
|
|
||||||
#[cfg(feature = "pounder_v1_1")]
|
#[cfg(feature = "pounder_v1_1")]
|
||||||
let pounder_stamper = {
|
let pounder_stamper = {
|
||||||
|
log::info!("Assuming Pounder v1.1 or later");
|
||||||
let etr_pin = gpioa.pa0.into_alternate_af3();
|
let etr_pin = gpioa.pa0.into_alternate_af3();
|
||||||
|
|
||||||
// The frequency in the constructor is dont-care, as we will modify the period + clock
|
// The frequency in the constructor is dont-care, as we will modify the period + clock
|
||||||
@ -968,13 +1018,13 @@ pub fn setup(
|
|||||||
digital_inputs,
|
digital_inputs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Enable the instruction cache.
|
||||||
|
core.SCB.enable_icache();
|
||||||
|
|
||||||
// info!("Version {} {}", build_info::PKG_VERSION, build_info::GIT_VERSION.unwrap());
|
// info!("Version {} {}", build_info::PKG_VERSION, build_info::GIT_VERSION.unwrap());
|
||||||
// info!("Built on {}", build_info::BUILT_TIME_UTC);
|
// info!("Built on {}", build_info::BUILT_TIME_UTC);
|
||||||
// info!("{} {}", build_info::RUSTC_VERSION, build_info::TARGET);
|
// info!("{} {}", build_info::RUSTC_VERSION, build_info::TARGET);
|
||||||
log::info!("setup() complete");
|
log::info!("setup() complete");
|
||||||
|
|
||||||
// Enable the instruction cache.
|
|
||||||
core.SCB.enable_icache();
|
|
||||||
|
|
||||||
(stabilizer, pounder)
|
(stabilizer, pounder)
|
||||||
}
|
}
|
||||||
|
@ -90,11 +90,11 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cortex_m_rt::exception]
|
#[cortex_m_rt::exception]
|
||||||
fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! {
|
unsafe fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! {
|
||||||
panic!("HardFault at {:#?}", ef);
|
panic!("HardFault at {:#?}", ef);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cortex_m_rt::exception]
|
#[cortex_m_rt::exception]
|
||||||
fn DefaultHandler(irqn: i16) {
|
unsafe fn DefaultHandler(irqn: i16) {
|
||||||
panic!("Unhandled exception (IRQn = {})", irqn);
|
panic!("Unhandled exception (IRQn = {})", irqn);
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,12 @@ use super::NetworkReference;
|
|||||||
use crate::hardware::design_parameters::SAMPLE_BUFFER_SIZE;
|
use crate::hardware::design_parameters::SAMPLE_BUFFER_SIZE;
|
||||||
|
|
||||||
// The number of data blocks that we will buffer in the queue.
|
// The number of data blocks that we will buffer in the queue.
|
||||||
type BlockBufferSize = heapless::consts::U30;
|
const BLOCK_BUFFER_SIZE: usize = 30;
|
||||||
|
|
||||||
pub fn setup_streaming(
|
pub fn setup_streaming(
|
||||||
stack: NetworkReference,
|
stack: NetworkReference,
|
||||||
) -> (BlockGenerator, DataStream) {
|
) -> (BlockGenerator, DataStream) {
|
||||||
let queue = cortex_m::singleton!(: Queue<AdcDacData, BlockBufferSize> = Queue::new()).unwrap();
|
let queue = cortex_m::singleton!(: Queue<AdcDacData, BLOCK_BUFFER_SIZE> = Queue::new()).unwrap();
|
||||||
|
|
||||||
let (producer, consumer) = queue.split();
|
let (producer, consumer) = queue.split();
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ pub fn setup_streaming(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn serialize_blocks<'a>(buffer: &'a mut [u8], max_buffer_size: usize, queue: &mut Consumer<'static,
|
pub fn serialize_blocks<'a>(buffer: &'a mut [u8], max_buffer_size: usize, queue: &mut Consumer<'static,
|
||||||
AdcDacData, BlockBufferSize>) -> &'a [u8] {
|
AdcDacData, BLOCK_BUFFER_SIZE>) -> &'a [u8] {
|
||||||
// While there is space in the buffer, serialize into it.
|
// While there is space in the buffer, serialize into it.
|
||||||
|
|
||||||
let block_size = (SAMPLE_BUFFER_SIZE * 2) * 2 * 2 + 8;
|
let block_size = (SAMPLE_BUFFER_SIZE * 2) * 2 * 2 + 8;
|
||||||
@ -69,12 +69,12 @@ pub struct AdcDacData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct BlockGenerator {
|
pub struct BlockGenerator {
|
||||||
queue: Producer<'static, AdcDacData, BlockBufferSize>,
|
queue: Producer<'static, AdcDacData, BLOCK_BUFFER_SIZE>,
|
||||||
current_id: u32,
|
current_id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockGenerator {
|
impl BlockGenerator {
|
||||||
pub fn new(queue: Producer<'static, AdcDacData, BlockBufferSize>) -> Self {
|
pub fn new(queue: Producer<'static, AdcDacData, BLOCK_BUFFER_SIZE>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
queue,
|
queue,
|
||||||
current_id: 0,
|
current_id: 0,
|
||||||
@ -103,7 +103,7 @@ impl BlockGenerator {
|
|||||||
pub struct DataStream {
|
pub struct DataStream {
|
||||||
stack: NetworkReference,
|
stack: NetworkReference,
|
||||||
socket: Option<<NetworkReference as UdpClientStack>::UdpSocket>,
|
socket: Option<<NetworkReference as UdpClientStack>::UdpSocket>,
|
||||||
queue: Consumer<'static, AdcDacData, BlockBufferSize>,
|
queue: Consumer<'static, AdcDacData, BLOCK_BUFFER_SIZE>,
|
||||||
remote: Option<SocketAddr>,
|
remote: Option<SocketAddr>,
|
||||||
buffer: [u8; 1024],
|
buffer: [u8; 1024],
|
||||||
}
|
}
|
||||||
@ -138,7 +138,7 @@ impl DataBlock {
|
|||||||
impl DataStream {
|
impl DataStream {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
stack: NetworkReference,
|
stack: NetworkReference,
|
||||||
consumer: Consumer<'static, AdcDacData, BlockBufferSize>,
|
consumer: Consumer<'static, AdcDacData, BLOCK_BUFFER_SIZE>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
stack,
|
stack,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use heapless::{consts, String, Vec};
|
use heapless::{String, Vec};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
@ -12,15 +12,15 @@ pub enum SettingsResponseCode {
|
|||||||
/// Represents a generic MQTT message.
|
/// Represents a generic MQTT message.
|
||||||
pub struct MqttMessage<'a> {
|
pub struct MqttMessage<'a> {
|
||||||
pub topic: &'a str,
|
pub topic: &'a str,
|
||||||
pub message: Vec<u8, consts::U128>,
|
pub message: Vec<u8, 128>,
|
||||||
pub properties: Vec<minimq::Property<'a>, consts::U1>,
|
pub properties: Vec<minimq::Property<'a>, 1>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The payload of the MQTT response message to a settings update request.
|
/// The payload of the MQTT response message to a settings update request.
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct SettingsResponse {
|
pub struct SettingsResponse {
|
||||||
code: u8,
|
code: u8,
|
||||||
msg: String<heapless::consts::U64>,
|
msg: String<64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MqttMessage<'a> {
|
impl<'a> MqttMessage<'a> {
|
||||||
@ -48,8 +48,7 @@ impl<'a> MqttMessage<'a> {
|
|||||||
.unwrap_or(&default_response);
|
.unwrap_or(&default_response);
|
||||||
|
|
||||||
// Associate any provided correlation data with the response.
|
// Associate any provided correlation data with the response.
|
||||||
let mut correlation_data: Vec<minimq::Property<'a>, consts::U1> =
|
let mut correlation_data: Vec<minimq::Property<'a>, 1> = Vec::new();
|
||||||
Vec::new();
|
|
||||||
if let Some(data) = properties
|
if let Some(data) = properties
|
||||||
.iter()
|
.iter()
|
||||||
.find(|prop| matches!(prop, minimq::Property::CorrelationData(_)))
|
.find(|prop| matches!(prop, minimq::Property::CorrelationData(_)))
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
///!
|
///!
|
||||||
///! Respones to settings updates are sent without quality-of-service guarantees, so there's no
|
///! Respones to settings updates are sent without quality-of-service guarantees, so there's no
|
||||||
///! guarantee that the requestee will be informed that settings have been applied.
|
///! guarantee that the requestee will be informed that settings have been applied.
|
||||||
use heapless::{consts, String};
|
use heapless::String;
|
||||||
|
|
||||||
use super::{MqttMessage, NetworkReference, SettingsResponse, UpdateState};
|
use super::{MqttMessage, NetworkReference, SettingsResponse, UpdateState};
|
||||||
use crate::hardware::design_parameters::MQTT_BROKER;
|
use crate::hardware::design_parameters::MQTT_BROKER;
|
||||||
@ -20,11 +20,11 @@ pub struct MiniconfClient<S>
|
|||||||
where
|
where
|
||||||
S: miniconf::Miniconf + Default + Clone,
|
S: miniconf::Miniconf + Default + Clone,
|
||||||
{
|
{
|
||||||
default_response_topic: String<consts::U128>,
|
default_response_topic: String<128>,
|
||||||
mqtt: minimq::Minimq<NetworkReference, 256>,
|
mqtt: minimq::Minimq<NetworkReference, 256>,
|
||||||
settings: S,
|
settings: S,
|
||||||
subscribed: bool,
|
subscribed: bool,
|
||||||
settings_prefix: String<consts::U64>,
|
settings_prefix: String<64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> MiniconfClient<S>
|
impl<S> MiniconfClient<S>
|
||||||
@ -41,10 +41,10 @@ where
|
|||||||
let mqtt =
|
let mqtt =
|
||||||
minimq::Minimq::new(MQTT_BROKER.into(), client_id, stack).unwrap();
|
minimq::Minimq::new(MQTT_BROKER.into(), client_id, stack).unwrap();
|
||||||
|
|
||||||
let mut response_topic: String<consts::U128> = String::from(prefix);
|
let mut response_topic: String<128> = String::from(prefix);
|
||||||
response_topic.push_str("/log").unwrap();
|
response_topic.push_str("/log").unwrap();
|
||||||
|
|
||||||
let mut settings_prefix: String<consts::U64> = String::from(prefix);
|
let mut settings_prefix: String<64> = String::from(prefix);
|
||||||
settings_prefix.push_str("/settings").unwrap();
|
settings_prefix.push_str("/settings").unwrap();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -81,7 +81,7 @@ where
|
|||||||
if !self.subscribed && mqtt_connected {
|
if !self.subscribed && mqtt_connected {
|
||||||
// Note(unwrap): We construct a string with two more characters than the prefix
|
// Note(unwrap): We construct a string with two more characters than the prefix
|
||||||
// strucutre, so we are guaranteed to have space for storage.
|
// strucutre, so we are guaranteed to have space for storage.
|
||||||
let mut settings_topic: String<consts::U66> =
|
let mut settings_topic: String<66> =
|
||||||
String::from(self.settings_prefix.as_str());
|
String::from(self.settings_prefix.as_str());
|
||||||
settings_topic.push_str("/#").unwrap();
|
settings_topic.push_str("/#").unwrap();
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
///! telemetry (via MQTT), configuration of run-time settings (via MQTT + Miniconf), and live data
|
///! telemetry (via MQTT), configuration of run-time settings (via MQTT + Miniconf), and live data
|
||||||
///! streaming over raw UDP/TCP sockets. This module encompasses the main processing routines
|
///! streaming over raw UDP/TCP sockets. This module encompasses the main processing routines
|
||||||
///! related to Stabilizer networking operations.
|
///! related to Stabilizer networking operations.
|
||||||
use heapless::{consts, String};
|
use heapless::String;
|
||||||
use miniconf::Miniconf;
|
use miniconf::Miniconf;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
@ -129,7 +129,6 @@ where
|
|||||||
/// # Returns
|
/// # Returns
|
||||||
/// An indication if any of the network users indicated a state change.
|
/// An indication if any of the network users indicated a state change.
|
||||||
pub fn update(&mut self) -> NetworkState {
|
pub fn update(&mut self) -> NetworkState {
|
||||||
super::debug::high();
|
|
||||||
// Update the MQTT clients.
|
// Update the MQTT clients.
|
||||||
self.telemetry.update();
|
self.telemetry.update();
|
||||||
|
|
||||||
@ -149,8 +148,6 @@ where
|
|||||||
UpdateState::NoChange => poll_result,
|
UpdateState::NoChange => poll_result,
|
||||||
};
|
};
|
||||||
|
|
||||||
super::debug::low();
|
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,7 +165,7 @@ fn get_client_id(
|
|||||||
app: &str,
|
app: &str,
|
||||||
client: &str,
|
client: &str,
|
||||||
mac: smoltcp_nal::smoltcp::wire::EthernetAddress,
|
mac: smoltcp_nal::smoltcp::wire::EthernetAddress,
|
||||||
) -> String<consts::U64> {
|
) -> String<64> {
|
||||||
let mut identifier = String::new();
|
let mut identifier = String::new();
|
||||||
write!(&mut identifier, "{}-{}-{}", app, mac, client).unwrap();
|
write!(&mut identifier, "{}-{}-{}", app, mac, client).unwrap();
|
||||||
identifier
|
identifier
|
||||||
@ -185,10 +182,10 @@ fn get_client_id(
|
|||||||
pub fn get_device_prefix(
|
pub fn get_device_prefix(
|
||||||
app: &str,
|
app: &str,
|
||||||
mac: smoltcp_nal::smoltcp::wire::EthernetAddress,
|
mac: smoltcp_nal::smoltcp::wire::EthernetAddress,
|
||||||
) -> String<consts::U128> {
|
) -> String<128> {
|
||||||
// Note(unwrap): The mac address + binary name must be short enough to fit into this string. If
|
// Note(unwrap): The mac address + binary name must be short enough to fit into this string. If
|
||||||
// they are defined too long, this will panic and the device will fail to boot.
|
// they are defined too long, this will panic and the device will fail to boot.
|
||||||
let mut prefix: String<consts::U128> = String::new();
|
let mut prefix: String<128> = String::new();
|
||||||
write!(&mut prefix, "dt/sinara/{}/{}", app, mac).unwrap();
|
write!(&mut prefix, "dt/sinara/{}/{}", app, mac).unwrap();
|
||||||
|
|
||||||
prefix
|
prefix
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
///! sampling frequency. Instead, the raw codes are stored and the telemetry is generated as
|
///! sampling frequency. Instead, the raw codes are stored and the telemetry is generated as
|
||||||
///! required immediately before transmission. This ensures that any slower computation required
|
///! required immediately before transmission. This ensures that any slower computation required
|
||||||
///! for unit conversion can be off-loaded to lower priority tasks.
|
///! for unit conversion can be off-loaded to lower priority tasks.
|
||||||
use heapless::{consts, String, Vec};
|
use heapless::{String, Vec};
|
||||||
use minimq::QoS;
|
use minimq::QoS;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ use crate::hardware::{
|
|||||||
/// The telemetry client for reporting telemetry data over MQTT.
|
/// The telemetry client for reporting telemetry data over MQTT.
|
||||||
pub struct TelemetryClient<T: Serialize> {
|
pub struct TelemetryClient<T: Serialize> {
|
||||||
mqtt: minimq::Minimq<NetworkReference, 256>,
|
mqtt: minimq::Minimq<NetworkReference, 256>,
|
||||||
telemetry_topic: String<consts::U128>,
|
telemetry_topic: String<128>,
|
||||||
_telemetry: core::marker::PhantomData<T>,
|
_telemetry: core::marker::PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ impl<T: Serialize> TelemetryClient<T> {
|
|||||||
let mqtt =
|
let mqtt =
|
||||||
minimq::Minimq::new(MQTT_BROKER.into(), client_id, stack).unwrap();
|
minimq::Minimq::new(MQTT_BROKER.into(), client_id, stack).unwrap();
|
||||||
|
|
||||||
let mut telemetry_topic: String<consts::U128> = String::from(prefix);
|
let mut telemetry_topic: String<128> = String::from(prefix);
|
||||||
telemetry_topic.push_str("/telemetry").unwrap();
|
telemetry_topic.push_str("/telemetry").unwrap();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -118,7 +118,7 @@ impl<T: Serialize> TelemetryClient<T> {
|
|||||||
/// # Args
|
/// # Args
|
||||||
/// * `telemetry` - The telemetry to report
|
/// * `telemetry` - The telemetry to report
|
||||||
pub fn publish(&mut self, telemetry: &T) {
|
pub fn publish(&mut self, telemetry: &T) {
|
||||||
let telemetry: Vec<u8, consts::U256> =
|
let telemetry: Vec<u8, 256> =
|
||||||
serde_json_core::to_vec(telemetry).unwrap();
|
serde_json_core::to_vec(telemetry).unwrap();
|
||||||
self.mqtt
|
self.mqtt
|
||||||
.client
|
.client
|
||||||
|
Loading…
Reference in New Issue
Block a user