Merge branch 'rj/log' into rj/itcm
* rj/log: refine panic handler and add some logging info hitl: kill probe-run cleanly set target-cpu=cortex-m7, MSRV 1.52.0, use probe-run README: document lockin, cleanup instructions, use probe-run CHANGELOG: update README: streamline docs a bit, add probe-run update hitl script remove rtt feature use rtt logging dsp/lowpass,lockin: const generics
This commit is contained in:
commit
8eef23da6b
|
@ -1,16 +1,11 @@
|
|||
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||
runner = "gdb-multiarch -q -x openocd.gdb"
|
||||
runner = "probe-run --chip STM32H743ZITx --speed 30000"
|
||||
# runner = "gdb-multiarch -q -x openocd.gdb"
|
||||
rustflags = [
|
||||
"-C", "link-arg=--nmagic",
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
# The target (below) defaults to cortex-m4
|
||||
# There currently are two different options to go beyond that:
|
||||
# 1. cortex-m7 has the right flags and instructions (FPU) but no instruction schedule yet
|
||||
# "-C", "target-cpu=cortex-m7",
|
||||
# 2. cortex-m4 with the additional fpv5 instructions and a potentially
|
||||
# better-than-nothing instruction schedule
|
||||
"-C", "target-feature=+fp-armv8d16",
|
||||
# When combined they are equivalent to (1) alone
|
||||
"-C", "link-arg=--nmagic",
|
||||
"-C", "target-cpu=cortex-m7",
|
||||
]
|
||||
|
||||
[build]
|
||||
|
|
|
@ -9,8 +9,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||
|
||||
### Added
|
||||
|
||||
* Telemetry
|
||||
* RTT logging
|
||||
|
||||
### Changed
|
||||
|
||||
* Const generics, bumping the MSRV to 1.51.0
|
||||
* `lockin-internal` and `lockin-external` have been merged into `lockin`
|
||||
* Set target CPU to cortex-m7, effectively bumping the MSRV to 1.52.0
|
||||
|
||||
### Fixed
|
||||
|
||||
## [v0.5.0] - 2021-04-21
|
||||
|
|
|
@ -139,17 +139,6 @@ dependencies = [
|
|||
"volatile-register",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m-log"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e202d2eac4e34adf7524a563e36623bae6f69cc0a73ef9bd22a4c93a5a806fa"
|
||||
dependencies = [
|
||||
"cortex-m 0.7.2",
|
||||
"cortex-m-semihosting",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m-rt"
|
||||
version = "0.6.13"
|
||||
|
@ -194,15 +183,6 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m-semihosting"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bffa6c1454368a6aa4811ae60964c38e6996d397ff8095a8b9211b1c1f749bc"
|
||||
dependencies = [
|
||||
"cortex-m 0.7.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_miniconf"
|
||||
version = "0.1.0"
|
||||
|
@ -218,7 +198,6 @@ name = "dsp"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"easybench",
|
||||
"generic-array 0.14.4",
|
||||
"libm",
|
||||
"miniconf",
|
||||
"ndarray",
|
||||
|
@ -541,16 +520,6 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "panic-semihosting"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d55dedd501dfd02514646e0af4d7016ce36bc12ae177ef52056989966a1eec"
|
||||
dependencies = [
|
||||
"cortex-m 0.7.2",
|
||||
"cortex-m-semihosting",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.5"
|
||||
|
@ -644,6 +613,26 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtt-logger"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d082d3a20a5d4f69ad509720de1777fe5aa2092ea1af51b254ff79113d46d2ea"
|
||||
dependencies = [
|
||||
"log",
|
||||
"rtt-target",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtt-target"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0869b4c5b6a6d8c5583fc473f9eb3423a170f77626b8c8a7fb18eddcda5770e2"
|
||||
dependencies = [
|
||||
"cortex-m 0.6.7",
|
||||
"ufmt-write",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
|
@ -745,7 +734,6 @@ dependencies = [
|
|||
"asm-delay",
|
||||
"cc",
|
||||
"cortex-m 0.6.7",
|
||||
"cortex-m-log",
|
||||
"cortex-m-rt",
|
||||
"cortex-m-rtic",
|
||||
"dsp",
|
||||
|
@ -758,8 +746,9 @@ dependencies = [
|
|||
"miniconf",
|
||||
"minimq",
|
||||
"nb 1.0.0",
|
||||
"panic-semihosting",
|
||||
"paste",
|
||||
"rtt-logger",
|
||||
"rtt-target",
|
||||
"serde",
|
||||
"serde-json-core",
|
||||
"shared-bus",
|
||||
|
@ -821,6 +810,12 @@ version = "1.13.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
|
||||
|
||||
[[package]]
|
||||
name = "ufmt-write"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.1"
|
||||
|
|
|
@ -30,9 +30,9 @@ members = ["ad9959", "dsp"]
|
|||
[dependencies]
|
||||
cortex-m = { version = "0.6", features = ["const-fn"] }
|
||||
cortex-m-rt = { version = "0.6", features = ["device"] }
|
||||
cortex-m-log = { version = "0.7", features = ["log-integration"] }
|
||||
log = "0.4"
|
||||
panic-semihosting = { version = "0.5", optional = true }
|
||||
log = { version = "0.4", features = ["max_level_trace", "release_max_level_info"] }
|
||||
rtt-target = { version = "0.2.1", features = ["cortex-m"] }
|
||||
rtt-logger = { version = "0.1" }
|
||||
serde = { version = "1.0", features = ["derive"], default-features = false }
|
||||
heapless = { version = "0.6", features = ["serde"] }
|
||||
cortex-m-rtic = "0.5.6"
|
||||
|
@ -76,7 +76,6 @@ git = "https://github.com/quartiq/minimq.git"
|
|||
rev = "d2ec3e8"
|
||||
|
||||
[features]
|
||||
semihosting = ["panic-semihosting", "cortex-m-log/semihosting"]
|
||||
bkpt = [ ]
|
||||
nightly = ["cortex-m/inline-asm", "dsp/nightly"]
|
||||
pounder_v1_1 = [ ]
|
||||
|
|
42
README.md
42
README.md
|
@ -10,10 +10,10 @@
|
|||
|
||||
## Applications
|
||||
|
||||
The Stabilizer firmware offeres a library of hardware and software functionality
|
||||
exposing input/output, timing, and digital signal processing features.
|
||||
An application can compose and configure these hardware and software components
|
||||
to implement different use cases. Several applications are provides by default
|
||||
This firmware offers a library of hardware and software functionality targeting the use of the Stabilizer hardware in various digital signal processing applications commonly occurring in Quantum Technology.
|
||||
It provides abstractions over the fast analog inputs and outputs, time stamping, Pounder DDS interfaces and a collection of tailored and optimized digital signal processing algorithms (IIR, FIR, Lockin, PLL, reciprocal PLL, Unwrapper, Lowpass, Cosine-Sine, Atan2).
|
||||
An application can compose and configure these hardware and software components to implement different use cases.
|
||||
Several applications are provides by default:
|
||||
|
||||
### Dual-IIR
|
||||
|
||||
|
@ -31,22 +31,34 @@ to implement different use cases. Several applications are provides by default
|
|||
|
||||
### Lockin
|
||||
|
||||
* Up to 800 kHz sampling
|
||||
* Up to 400 kHz modulation frequency
|
||||
* Reciprocal PLL for external reference
|
||||
* Internal reference
|
||||
* Adjustable PLL and locking time constants
|
||||
* Adjustable phase offset and harmonic index
|
||||
* Different output modes (in-phase, quadrature, magnitude, log2 power, phase, frequency)
|
||||
|
||||
## Minimal bootstrapping documentation
|
||||
|
||||
* Clone or download this
|
||||
* Get [rustup](https://rustup.rs/)
|
||||
* `rustup target add thumbv7em-none-eabihf`
|
||||
* `cargo build --release`
|
||||
* Minimum supported Rust version (MSRV) is 1.52.0
|
||||
* Install target support: `rustup target add thumbv7em-none-eabihf`
|
||||
* Install `probe-run`: `cargo install probe-run`
|
||||
* `cargo run --release --bin dual-iir`
|
||||
* When using debug (non `--release`) mode, increase the sample interval significantly.
|
||||
The added error checking code and missing optimizations may lead to the code
|
||||
missing deadlines and panicing.
|
||||
|
||||
### Using Cargo-embed
|
||||
## Alternative flashing tools
|
||||
|
||||
### Cargo-embed
|
||||
|
||||
* Install `cargo-embed`: `cargo install cargo-embed`
|
||||
* Program the device: `cargo embed --bin dual-iir --release`
|
||||
|
||||
### Using GDB/OpenOCD
|
||||
### GDB/OpenOCD
|
||||
|
||||
* Get a recent openocd, a JTAG adapter ("st-link" or some clone) and
|
||||
everything connected and permissions setup. Most
|
||||
|
@ -56,24 +68,24 @@ to implement different use cases. Several applications are provides by default
|
|||
* `openocd -f stabilizer.cfg` and leave it running
|
||||
* `cargo run --release`
|
||||
|
||||
### Using USB-DFU
|
||||
### USB-DFU
|
||||
|
||||
* Get [cargo-binutils](https://github.com/rust-embedded/cargo-binutils/)
|
||||
* `cargo objcopy --release --bin dual-iir -- -O binary dual-iir.bin` or `arm-none-eabi-objcopy -O binary target/thumbv7em-none-eabihf/release/dual-iir dual-iir.bin`
|
||||
* Install the DFU USB tool (`dfu-util`)
|
||||
* Connect to the Micro USB connector below the RJ45
|
||||
* Short JC2/BOOT
|
||||
* Get [cargo-binutils](https://github.com/rust-embedded/cargo-binutils/)
|
||||
* `cargo objcopy --release --bin dual-iir -- -O binary dual-iir.bin` or `arm-none-eabi-objcopy -O binary target/thumbv7em-none-eabihf/release/dual-iir dual-iir.bin`
|
||||
* `dfu-util -a 0 -s 0x08000000:leave -D dual-iir.bin`
|
||||
|
||||
### Using ST-Link virtual mass storage
|
||||
### ST-Link virtual mass storage
|
||||
|
||||
* Get [cargo-binutils](https://github.com/rust-embedded/cargo-binutils/)
|
||||
* `cargo objcopy --release --bin dual-iir -- -O binary dual-iir.bin` or `arm-none-eabi-objcopy -O binary target/thumbv7em-none-eabihf/release/dual-iir dual-iir.bin`
|
||||
* Prepare `dual-iir.bin` like above
|
||||
* Connect the ST-Link debugger
|
||||
* copy `dual-iir.bin` to the `NODE_H743ZI` USB disk
|
||||
* Copy `dual-iir.bin` to the `NODE_H743ZI` virtual mass storage device
|
||||
|
||||
## Protocol
|
||||
|
||||
Stabilizer can be configured via MQTT. Refer to
|
||||
[`miniconf`](https://github.com/quartiq/miniconf) for more information about topics.
|
||||
A basic command line interface is available in [`miniconf.py`](miniconf.py).
|
||||
Telemetry is published via MQTT as well.
|
||||
|
|
|
@ -7,7 +7,6 @@ edition = "2018"
|
|||
[dependencies]
|
||||
libm = "0.2.1"
|
||||
serde = { version = "1.0", features = ["derive"], default-features = false }
|
||||
generic-array = "0.14"
|
||||
num = { version = "0.4.0", default-features = false }
|
||||
miniconf = "0.1"
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use core::f32::consts::PI;
|
||||
|
||||
use easybench::bench_env;
|
||||
use generic_array::typenum::U4;
|
||||
|
||||
use dsp::{atan2, cossin, iir, iir_int, Lowpass, PLL, RPLL};
|
||||
|
||||
|
@ -72,13 +71,13 @@ fn iir_bench() {
|
|||
}
|
||||
|
||||
fn lowpass_bench() {
|
||||
let mut dut = Lowpass::<U4>::default();
|
||||
let mut dut = Lowpass::<4>::default();
|
||||
println!(
|
||||
"Lowpass::<U4>::update(x, k): {}",
|
||||
"Lowpass::<4>::update(x, k): {}",
|
||||
bench_env((0x32421, 14), |(x, k)| dut.update(*x, *k))
|
||||
);
|
||||
println!(
|
||||
"Lowpass::<U4>::update(x, 14): {}",
|
||||
"Lowpass::<4>::update(x, 14): {}",
|
||||
bench_env(0x32421, |x| dut.update(*x, 14))
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use super::{Complex, ComplexExt, Lowpass, MulScaled};
|
||||
use generic_array::ArrayLength;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Lockin<N: ArrayLength<i32>> {
|
||||
pub struct Lockin<const N: usize> {
|
||||
state: [Lowpass<N>; 2],
|
||||
}
|
||||
|
||||
impl<N: ArrayLength<i32>> Lockin<N> {
|
||||
impl<const N: usize> Lockin<N> {
|
||||
/// Update the lockin with a sample taken at a given phase.
|
||||
pub fn update(&mut self, sample: i32, phase: i32, k: u8) -> Complex<i32> {
|
||||
// Get the LO signal for demodulation and mix the sample;
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
use generic_array::{ArrayLength, GenericArray};
|
||||
|
||||
/// Arbitrary order, high dynamic range, wide coefficient range,
|
||||
/// lowpass filter implementation. DC gain is 1.
|
||||
///
|
||||
/// Type argument N is the filter order.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Lowpass<N: ArrayLength<i32>> {
|
||||
#[derive(Clone)]
|
||||
pub struct Lowpass<const N: usize> {
|
||||
// IIR state storage
|
||||
y: GenericArray<i32, N>,
|
||||
y: [i32; N],
|
||||
}
|
||||
|
||||
impl<N: ArrayLength<i32>> Lowpass<N> {
|
||||
impl<const N: usize> Default for Lowpass<N> {
|
||||
fn default() -> Self {
|
||||
Lowpass { y: [0i32; N] }
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Lowpass<N> {
|
||||
/// Update the filter with a new sample.
|
||||
///
|
||||
/// # Args
|
||||
|
|
|
@ -15,9 +15,9 @@ python3 -m venv --system-site-packages py
|
|||
. py/bin/activate
|
||||
python3 -m pip install -r requirements.txt
|
||||
|
||||
cargo flash --elf target/thumbv7em-none-eabihf/release/dual-iir --chip STM32H743ZITx
|
||||
probe-run --chip STM32H743ZITx target/thumbv7em-none-eabihf/release/dual-iir &
|
||||
|
||||
# Before attempting to ping the device, sleep to allow Stabilizer to boot.
|
||||
# Sleep to allow flashing, booting, DHCP, MQTT
|
||||
sleep 30
|
||||
|
||||
# Test pinging Stabilizer. This exercises that:
|
||||
|
@ -30,3 +30,6 @@ ping -c 5 -w 20 stabilizer-hitl
|
|||
python3 miniconf.py dt/sinara/dual-iir/04-91-62-d9-7e-5f afe/0='"G2"'
|
||||
python3 miniconf.py dt/sinara/dual-iir/04-91-62-d9-7e-5f afe/0='"G1"' iir_ch/0/0=\
|
||||
'{"y_min": -32767, "y_max": 32767, "y_offset": 0, "ba": [1.0, 0, 0, 0, 0]}'
|
||||
|
||||
kill $(jobs -p)
|
||||
wait || true
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#![no_main]
|
||||
|
||||
use embedded_hal::digital::v2::InputPin;
|
||||
use generic_array::typenum::U4;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
|
@ -92,7 +91,7 @@ const APP: () = {
|
|||
|
||||
timestamper: InputStamper,
|
||||
pll: RPLL,
|
||||
lockin: Lockin<U4>,
|
||||
lockin: Lockin<4>,
|
||||
}
|
||||
|
||||
#[init(spawn=[settings_update, telemetry])]
|
||||
|
|
|
@ -145,19 +145,19 @@ pub fn setup(
|
|||
.pll2_q_ck(100.mhz())
|
||||
.freeze(vos, &device.SYSCFG);
|
||||
|
||||
#[cfg(feature = "semihosting")]
|
||||
// Set up RTT logging
|
||||
{
|
||||
use cortex_m_log::log::{init as init_log, Logger};
|
||||
use cortex_m_log::printer::semihosting::{hio::HStdout, InterruptOk};
|
||||
use log::LevelFilter;
|
||||
static mut LOGGER: Option<Logger<InterruptOk<HStdout>>> = None;
|
||||
let logger = Logger {
|
||||
inner: InterruptOk::<_>::stdout().unwrap(),
|
||||
level: LevelFilter::Info,
|
||||
};
|
||||
let logger = unsafe { LOGGER.get_or_insert(logger) };
|
||||
// Enable debug during WFE/WFI-induced sleep
|
||||
device.DBGMCU.cr.modify(|_, w| w.dbgsleep_d1().set_bit());
|
||||
|
||||
init_log(logger).unwrap();
|
||||
use rtt_logger::RTTLogger;
|
||||
|
||||
static LOGGER: RTTLogger = RTTLogger::new(log::LevelFilter::Info);
|
||||
rtt_target::rtt_init_print!(NoBlockSkip, 1024);
|
||||
log::set_logger(&LOGGER)
|
||||
.map(|()| log::set_max_level(log::LevelFilter::Trace))
|
||||
.unwrap();
|
||||
log::info!("starting...");
|
||||
}
|
||||
|
||||
// Set up the system timer for RTIC scheduling.
|
||||
|
@ -537,6 +537,7 @@ pub fn setup(
|
|||
&mut eeprom_i2c,
|
||||
&mut delay,
|
||||
));
|
||||
log::info!("EUI48: {}", mac_addr);
|
||||
|
||||
let network_devices = {
|
||||
// Configure the ethernet controller
|
||||
|
@ -673,6 +674,7 @@ pub fn setup(
|
|||
let pounder_pgood = gpiob.pb13.into_pull_down_input();
|
||||
delay.delay_ms(2u8);
|
||||
let pounder = if pounder_pgood.is_high().unwrap() {
|
||||
log::info!("Found Pounder");
|
||||
let ad9959 = {
|
||||
let qspi_interface = {
|
||||
// Instantiate the QUADSPI pins and peripheral interface.
|
||||
|
@ -935,6 +937,7 @@ pub fn setup(
|
|||
// info!("Version {} {}", build_info::PKG_VERSION, build_info::GIT_VERSION.unwrap());
|
||||
// info!("Built on {}", build_info::BUILT_TIME_UTC);
|
||||
// info!("{} {}", build_info::RUSTC_VERSION, build_info::TARGET);
|
||||
log::info!("setup() complete");
|
||||
|
||||
// Enable the instruction cache.
|
||||
core.SCB.enable_icache();
|
||||
|
|
|
@ -4,9 +4,6 @@ use stm32h7xx_hal as hal;
|
|||
// Re-export for the DigitalInputs below:
|
||||
pub use embedded_hal::digital::v2::InputPin;
|
||||
|
||||
#[cfg(feature = "semihosting")]
|
||||
use panic_semihosting as _;
|
||||
|
||||
mod adc;
|
||||
mod afe;
|
||||
mod configuration;
|
||||
|
@ -59,17 +56,37 @@ pub use configuration::{setup, PounderDevices, StabilizerDevices};
|
|||
|
||||
#[inline(never)]
|
||||
#[panic_handler]
|
||||
#[cfg(all(not(feature = "semihosting")))]
|
||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||
let gpiod = unsafe { &*hal::stm32::GPIOD::ptr() };
|
||||
// Turn on both red LEDs, FP_LED_1, FP_LED_3
|
||||
gpiod.odr.modify(|_, w| w.odr6().high().odr12().high());
|
||||
loop {
|
||||
// Halt
|
||||
core::sync::atomic::compiler_fence(
|
||||
core::sync::atomic::Ordering::SeqCst,
|
||||
);
|
||||
fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||
use core::{
|
||||
fmt::Write,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
use cortex_m::asm;
|
||||
use rtt_target::{ChannelMode, UpChannel};
|
||||
|
||||
cortex_m::interrupt::disable();
|
||||
|
||||
// Recursion protection
|
||||
static PANICKED: AtomicBool = AtomicBool::new(false);
|
||||
while PANICKED.load(Ordering::Relaxed) {
|
||||
asm::bkpt();
|
||||
}
|
||||
PANICKED.store(true, Ordering::Relaxed);
|
||||
|
||||
// Turn on both red LEDs, FP_LED_1, FP_LED_3
|
||||
let gpiod = unsafe { &*hal::stm32::GPIOD::ptr() };
|
||||
gpiod.odr.modify(|_, w| w.odr6().high().odr12().high());
|
||||
|
||||
// Analogous to panic-rtt-target
|
||||
if let Some(mut channel) = unsafe { UpChannel::conjure(0) } {
|
||||
channel.set_mode(ChannelMode::BlockIfFull);
|
||||
writeln!(channel, "{}", info).ok();
|
||||
}
|
||||
|
||||
// Abort
|
||||
asm::udf();
|
||||
// Halt
|
||||
// loop { core::sync::atomic::compiler_fence(Ordering::SeqCst); }
|
||||
}
|
||||
|
||||
#[cortex_m_rt::exception]
|
||||
|
|
Loading…
Reference in New Issue