Addressing PR review
This commit is contained in:
parent
fc81f3d55d
commit
67b6990fc0
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -517,7 +517,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "stm32h7xx-hal"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/quartiq/stm32h7xx-hal?branch=feature/number-of-transfers#e70a78788e74be5281321213b53e8cd1d213550e"
|
||||
source = "git+https://github.com/stm32-rs/stm32h7xx-hal?branch=dma#25ee0f3a9ae27d1fd6bb390d6045aa312f29f096"
|
||||
dependencies = [
|
||||
"bare-metal 1.0.0",
|
||||
"cast",
|
||||
|
@ -53,8 +53,8 @@ default-features = false
|
||||
|
||||
[dependencies.stm32h7xx-hal]
|
||||
features = ["stm32h743v", "rt", "unproven", "ethernet", "quadspi"]
|
||||
git = "https://github.com/quartiq/stm32h7xx-hal"
|
||||
branch = "feature/number-of-transfers"
|
||||
git = "https://github.com/stm32-rs/stm32h7xx-hal"
|
||||
branch = "dma"
|
||||
|
||||
[features]
|
||||
semihosting = ["panic-semihosting", "cortex-m-log/semihosting"]
|
||||
|
@ -18,6 +18,9 @@ load
|
||||
# tbreak cortex_m_rt::reset_handler
|
||||
monitor reset halt
|
||||
|
||||
source ../../PyCortexMDebug/cmdebug/svd_gdb.py
|
||||
svd_load ~/Downloads/STM32H743x.svd
|
||||
|
||||
# cycle counter delta tool, place two bkpts around the section
|
||||
set var $cc=0xe0001004
|
||||
define qq
|
||||
|
@ -1,9 +1,11 @@
|
||||
use super::hal::time::MegaHertz;
|
||||
|
||||
/// The ADC setup time is the number of seconds after the CSn line goes low before the serial clock
|
||||
/// may begin. This is used for performing the internal ADC conversion.
|
||||
pub const ADC_SETUP_TIME: f32 = 220e-9;
|
||||
|
||||
/// The maximum DAC/ADC serial clock line frequency. This is a hardware limit.
|
||||
pub const ADC_DAC_SCK_MHZ_MAX: u32 = 50;
|
||||
pub const ADC_DAC_SCK_MAX: MegaHertz = MegaHertz(50);
|
||||
|
||||
/// The optimal counting frequency of the hardware timers used for timestamping and sampling.
|
||||
pub const TIMER_FREQUENCY_MHZ: u32 = 100;
|
||||
pub const TIMER_FREQUENCY: MegaHertz = MegaHertz(100);
|
||||
|
@ -24,7 +24,41 @@
|
||||
///!
|
||||
///! This module only supports DI0 for timestamping due to trigger constraints on the DIx pins. If
|
||||
///! timestamping is desired in DI1, a separate timer + capture channel will be necessary.
|
||||
use super::{hal, timers};
|
||||
use super::{hal, timers, SAMPLE_BUFFER_SIZE, ADC_SAMPLE_TICKS};
|
||||
|
||||
/// Calculate the period of the digital input timestampe timer.
|
||||
///
|
||||
/// # Note
|
||||
/// The period returned will be 1 less than the required period in timer ticks. The value returned
|
||||
/// can be immediately programmed into a hardware timer period register.
|
||||
///
|
||||
/// The period is calcualted to be some power-of-two multiple of the batch size, such that N batches
|
||||
/// will occur between each timestamp timer overflow.
|
||||
///
|
||||
/// # Returns
|
||||
/// A 32-bit value that can be programmed into a hardware timer period register.
|
||||
pub fn calculate_timestamp_timer_period() -> u32 {
|
||||
// Calculate how long a single batch requires in timer ticks.
|
||||
let batch_duration_ticks: u64 = SAMPLE_BUFFER_SIZE as u64 * ADC_SAMPLE_TICKS as u64;
|
||||
|
||||
// Calculate the largest power-of-two that is less than or equal to
|
||||
// `batches_per_overflow`. This is completed by eliminating the least significant
|
||||
// bits of the value until only the msb remains, which is always a power of two.
|
||||
let batches_per_overflow: u64 =
|
||||
(1u64 + u32::MAX as u64) / batch_duration_ticks;
|
||||
let mut j = batches_per_overflow;
|
||||
while (j & (j - 1)) != 0 {
|
||||
j = j & (j - 1);
|
||||
}
|
||||
|
||||
// Once the number of batches per timestamp overflow is calculated, we can figure out the final
|
||||
// period of the timestamp timer. The period is always 1 larger than the value configured in the
|
||||
// register.
|
||||
let period: u64 = batch_duration_ticks * j - 1u64;
|
||||
assert!(period < u32::MAX as u64);
|
||||
|
||||
period as u32
|
||||
}
|
||||
|
||||
/// The timestamper for DI0 reference clock inputs.
|
||||
pub struct InputStamper {
|
||||
@ -45,7 +79,7 @@ impl InputStamper {
|
||||
// Utilize the TIM5 CH4 as an input capture channel - use TI4 (the DI0 input trigger) as the
|
||||
// capture source.
|
||||
let input_capture =
|
||||
timer_channel.to_input_capture(timers::tim5::CC4S_A::TI4);
|
||||
timer_channel.into_input_capture(timers::tim5::CC4S_A::TI4);
|
||||
|
||||
Self {
|
||||
capture_channel: input_capture,
|
||||
|
43
src/main.rs
43
src/main.rs
@ -30,8 +30,6 @@ extern crate panic_halt;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use core::convert::TryInto;
|
||||
|
||||
// use core::sync::atomic::{AtomicU32, AtomicBool, Ordering};
|
||||
use cortex_m_rt::exception;
|
||||
use rtic::cyccnt::{Instant, U32Ext};
|
||||
@ -294,10 +292,10 @@ const APP: () = {
|
||||
// Configure the timer to count at the designed tick rate. We will manually set the
|
||||
// period below.
|
||||
timer2.pause();
|
||||
timer2.set_tick_freq(design_parameters::TIMER_FREQUENCY_MHZ.mhz());
|
||||
timer2.set_tick_freq(design_parameters::TIMER_FREQUENCY);
|
||||
|
||||
let mut sampling_timer = timers::SamplingTimer::new(timer2);
|
||||
sampling_timer.set_period(ADC_SAMPLE_TICKS - 1);
|
||||
sampling_timer.set_period_ticks(ADC_SAMPLE_TICKS - 1);
|
||||
|
||||
sampling_timer
|
||||
};
|
||||
@ -313,32 +311,15 @@ const APP: () = {
|
||||
// Configure the timer to count at the designed tick rate. We will manually set the
|
||||
// period below.
|
||||
timer5.pause();
|
||||
timer5.set_tick_freq(design_parameters::TIMER_FREQUENCY_MHZ.mhz());
|
||||
timer5.set_tick_freq(design_parameters::TIMER_FREQUENCY);
|
||||
|
||||
// The time stamp timer must run at exactly a multiple of the sample timer based on the
|
||||
// batch size. To accomodate this, we manually set the period identical to the sample
|
||||
// timer, but use a prescaler that is `BATCH_SIZE` longer.
|
||||
// batch size. To accomodate this, we manually set the prescaler identical to the sample
|
||||
// timer, but use a period that is longer.
|
||||
let mut timer = timers::TimestampTimer::new(timer5);
|
||||
|
||||
let period: u32 = {
|
||||
let batch_duration: u64 =
|
||||
SAMPLE_BUFFER_SIZE as u64 * ADC_SAMPLE_TICKS as u64;
|
||||
let batches_per_overflow: u64 =
|
||||
(1u64 + u32::MAX as u64) / batch_duration;
|
||||
|
||||
// Calculate the largest power-of-two that is less than `batches_per_overflow`.
|
||||
// This is completed by eliminating the least significant bits of the value until
|
||||
// only the msb remains, which is always a power of two.
|
||||
let mut j = batches_per_overflow;
|
||||
while (j & (j - 1)) != 0 {
|
||||
j = j & (j - 1);
|
||||
}
|
||||
|
||||
let period: u64 = batch_duration * j - 1u64;
|
||||
period.try_into().unwrap()
|
||||
};
|
||||
|
||||
timer.set_period(period);
|
||||
let period = digital_input_stamper::calculate_timestamp_timer_period();
|
||||
timer.set_period_ticks(period);
|
||||
|
||||
timer
|
||||
};
|
||||
@ -372,7 +353,7 @@ const APP: () = {
|
||||
let spi: hal::spi::Spi<_, _, u16> = dp.SPI2.spi(
|
||||
(spi_sck, spi_miso, hal::spi::NoMosi),
|
||||
config,
|
||||
design_parameters::ADC_DAC_SCK_MHZ_MAX.mhz(),
|
||||
design_parameters::ADC_DAC_SCK_MAX,
|
||||
ccdr.peripheral.SPI2,
|
||||
&ccdr.clocks,
|
||||
);
|
||||
@ -410,7 +391,7 @@ const APP: () = {
|
||||
let spi: hal::spi::Spi<_, _, u16> = dp.SPI3.spi(
|
||||
(spi_sck, spi_miso, hal::spi::NoMosi),
|
||||
config,
|
||||
design_parameters::ADC_DAC_SCK_MHZ_MAX.mhz(),
|
||||
design_parameters::ADC_DAC_SCK_MAX,
|
||||
ccdr.peripheral.SPI3,
|
||||
&ccdr.clocks,
|
||||
);
|
||||
@ -460,7 +441,7 @@ const APP: () = {
|
||||
dp.SPI4.spi(
|
||||
(spi_sck, spi_miso, hal::spi::NoMosi),
|
||||
config,
|
||||
design_parameters::ADC_DAC_SCK_MHZ_MAX.mhz(),
|
||||
design_parameters::ADC_DAC_SCK_MAX,
|
||||
ccdr.peripheral.SPI4,
|
||||
&ccdr.clocks,
|
||||
)
|
||||
@ -492,7 +473,7 @@ const APP: () = {
|
||||
dp.SPI5.spi(
|
||||
(spi_sck, spi_miso, hal::spi::NoMosi),
|
||||
config,
|
||||
design_parameters::ADC_DAC_SCK_MHZ_MAX.mhz(),
|
||||
design_parameters::ADC_DAC_SCK_MAX,
|
||||
ccdr.peripheral.SPI5,
|
||||
&ccdr.clocks,
|
||||
)
|
||||
@ -702,7 +683,7 @@ const APP: () = {
|
||||
|
||||
// Ensure that we have enough time for an IO-update every sample.
|
||||
let sample_frequency =
|
||||
(design_parameters::TIMER_FREQUENCY_MHZ as f32
|
||||
(design_parameters::TIMER_FREQUENCY.0 as f32
|
||||
* 1_000_000.0)
|
||||
/ ADC_SAMPLE_TICKS as f32;
|
||||
|
||||
|
@ -41,7 +41,7 @@ macro_rules! timer_channels {
|
||||
|
||||
/// Manually set the period of the timer.
|
||||
#[allow(dead_code)]
|
||||
pub fn set_period(&mut self, period: u32) {
|
||||
pub fn set_period_ticks(&mut self, period: u32) {
|
||||
let regs = unsafe { &*hal::stm32::$TY::ptr() };
|
||||
regs.arr.write(|w| w.arr().bits(period));
|
||||
}
|
||||
@ -136,7 +136,7 @@ macro_rules! timer_channels {
|
||||
/// # Args
|
||||
/// * `input` - The input source for the input capture event.
|
||||
#[allow(dead_code)]
|
||||
pub fn to_input_capture(self, input: hal::stm32::tim2::[< $ccmrx _input >]::[< CC $index S_A >]) -> [< Channel $index InputCapture >]{
|
||||
pub fn into_input_capture(self, input: hal::stm32::tim2::[< $ccmrx _input >]::[< CC $index S_A >]) -> [< Channel $index InputCapture >]{
|
||||
let regs = unsafe { &*<$TY>::ptr() };
|
||||
regs.[< $ccmrx _input >]().modify(|_, w| w.[< cc $index s>]().variant(input));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user