pounder timestmper: don't use DMA
* One sample per batch is typical and sufficient. * DMA has more overhead than direct read for one sample.
This commit is contained in:
parent
f8fa297b20
commit
26b261364f
@ -233,11 +233,6 @@ pub fn setup(
|
|||||||
let dma_streams =
|
let dma_streams =
|
||||||
hal::dma::dma::StreamsTuple::new(device.DMA1, ccdr.peripheral.DMA1);
|
hal::dma::dma::StreamsTuple::new(device.DMA1, ccdr.peripheral.DMA1);
|
||||||
|
|
||||||
// Early, before the DMA1 peripherals (#272)
|
|
||||||
#[cfg(feature = "pounder_v1_1")]
|
|
||||||
let dma2_streams =
|
|
||||||
hal::dma::dma::StreamsTuple::new(device.DMA2, ccdr.peripheral.DMA2);
|
|
||||||
|
|
||||||
// Configure timer 2 to trigger conversions for the ADC
|
// Configure timer 2 to trigger conversions for the ADC
|
||||||
let mut sampling_timer = {
|
let mut sampling_timer = {
|
||||||
// The timer frequency is manually adjusted below, so the 1KHz setting here is a
|
// The timer frequency is manually adjusted below, so the 1KHz setting here is a
|
||||||
@ -946,7 +941,6 @@ pub fn setup(
|
|||||||
|
|
||||||
pounder::timestamp::Timestamper::new(
|
pounder::timestamp::Timestamper::new(
|
||||||
timestamp_timer,
|
timestamp_timer,
|
||||||
dma2_streams.0,
|
|
||||||
tim8_channels.ch1,
|
tim8_channels.ch1,
|
||||||
&mut sampling_timer,
|
&mut sampling_timer,
|
||||||
etr_pin,
|
etr_pin,
|
||||||
|
@ -24,27 +24,12 @@
|
|||||||
///! schedule.
|
///! schedule.
|
||||||
use stm32h7xx_hal as hal;
|
use stm32h7xx_hal as hal;
|
||||||
|
|
||||||
use hal::dma::{dma::DmaConfig, PeripheralToMemory, Transfer};
|
use crate::hardware::timers;
|
||||||
|
|
||||||
use crate::hardware::{design_parameters::SAMPLE_BUFFER_SIZE, timers};
|
|
||||||
|
|
||||||
// Three buffers are required for double buffered mode - 2 are owned by the DMA stream and 1 is the
|
|
||||||
// working data provided to the application. These buffers must exist in a DMA-accessible memory
|
|
||||||
// region. Note that AXISRAM is not initialized on boot, so their initial contents are undefined.
|
|
||||||
#[link_section = ".axisram.buffers"]
|
|
||||||
static mut BUF: [[u16; SAMPLE_BUFFER_SIZE]; 3] = [[0; SAMPLE_BUFFER_SIZE]; 3];
|
|
||||||
|
|
||||||
/// Software unit to timestamp stabilizer ADC samples using an external pounder reference clock.
|
/// Software unit to timestamp stabilizer ADC samples using an external pounder reference clock.
|
||||||
pub struct Timestamper {
|
pub struct Timestamper {
|
||||||
next_buffer: Option<&'static mut [u16; SAMPLE_BUFFER_SIZE]>,
|
|
||||||
timer: timers::PounderTimestampTimer,
|
timer: timers::PounderTimestampTimer,
|
||||||
transfer: Transfer<
|
capture_channel: timers::tim8::Channel1InputCapture,
|
||||||
hal::dma::dma::Stream0<hal::stm32::DMA2>,
|
|
||||||
timers::tim8::Channel1InputCapture,
|
|
||||||
PeripheralToMemory,
|
|
||||||
&'static mut [u16; SAMPLE_BUFFER_SIZE],
|
|
||||||
hal::dma::DBTransfer,
|
|
||||||
>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Timestamper {
|
impl Timestamper {
|
||||||
@ -65,18 +50,12 @@ impl Timestamper {
|
|||||||
/// The new pounder timestamper in an operational state.
|
/// The new pounder timestamper in an operational state.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
mut timestamp_timer: timers::PounderTimestampTimer,
|
mut timestamp_timer: timers::PounderTimestampTimer,
|
||||||
stream: hal::dma::dma::Stream0<hal::stm32::DMA2>,
|
|
||||||
capture_channel: timers::tim8::Channel1,
|
capture_channel: timers::tim8::Channel1,
|
||||||
sampling_timer: &mut timers::SamplingTimer,
|
sampling_timer: &mut timers::SamplingTimer,
|
||||||
_clock_input: hal::gpio::gpioa::PA0<
|
_clock_input: hal::gpio::gpioa::PA0<
|
||||||
hal::gpio::Alternate<hal::gpio::AF3>,
|
hal::gpio::Alternate<hal::gpio::AF3>,
|
||||||
>,
|
>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let config = DmaConfig::default()
|
|
||||||
.memory_increment(true)
|
|
||||||
.circular_buffer(true)
|
|
||||||
.double_buffer(true);
|
|
||||||
|
|
||||||
// The sampling timer should generate a trigger output when CH1 comparison occurs.
|
// The sampling timer should generate a trigger output when CH1 comparison occurs.
|
||||||
sampling_timer.generate_trigger(timers::TriggerGenerator::ComparePulse);
|
sampling_timer.generate_trigger(timers::TriggerGenerator::ComparePulse);
|
||||||
|
|
||||||
@ -87,62 +66,29 @@ impl Timestamper {
|
|||||||
// The capture channel should capture whenever the trigger input occurs.
|
// The capture channel should capture whenever the trigger input occurs.
|
||||||
let input_capture = capture_channel
|
let input_capture = capture_channel
|
||||||
.into_input_capture(timers::tim8::CaptureSource1::TRC);
|
.into_input_capture(timers::tim8::CaptureSource1::TRC);
|
||||||
input_capture.listen_dma();
|
|
||||||
|
|
||||||
// The data transfer is always a transfer of data from the peripheral to a RAM buffer.
|
|
||||||
let data_transfer: Transfer<_, _, PeripheralToMemory, _, _> =
|
|
||||||
Transfer::init(
|
|
||||||
stream,
|
|
||||||
input_capture,
|
|
||||||
// Note(unsafe): BUF[0] and BUF[1] are "owned" by this peripheral.
|
|
||||||
// They shall not be used anywhere else in the module.
|
|
||||||
unsafe { &mut BUF[0] },
|
|
||||||
unsafe { Some(&mut BUF[1]) },
|
|
||||||
config,
|
|
||||||
);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
timer: timestamp_timer,
|
timer: timestamp_timer,
|
||||||
transfer: data_transfer,
|
capture_channel: input_capture,
|
||||||
|
|
||||||
// Note(unsafe): BUF[2] is "owned" by this peripheral. It shall not be used anywhere
|
|
||||||
// else in the module.
|
|
||||||
next_buffer: unsafe { Some(&mut BUF[2]) },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start the DMA transfer for collecting timestamps.
|
/// Start collecting timestamps.
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn start(&mut self) {
|
pub fn start(&mut self) {
|
||||||
self.transfer
|
self.capture_channel.enable();
|
||||||
.start(|capture_channel| capture_channel.enable());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the period of the underlying timestamp timer.
|
/// Update the period of the underlying timestamp timer.
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn update_period(&mut self, period: u16) {
|
pub fn update_period(&mut self, period: u16) {
|
||||||
self.timer.set_period_ticks(period);
|
self.timer.set_period_ticks(period);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain a buffer filled with timestamps.
|
/// Obtain a timestamp.
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// A reference to the underlying buffer that has been filled with timestamps.
|
/// A `Result` potentially indicating capture overflow and containing a `Option` of a captured
|
||||||
#[allow(dead_code)]
|
/// timestamp.
|
||||||
pub fn acquire_buffer(&mut self) -> &[u16; SAMPLE_BUFFER_SIZE] {
|
pub fn latest_timestamp(&mut self) -> Result<Option<u16>, Option<u16>> {
|
||||||
// Wait for the transfer to fully complete before continuing.
|
self.capture_channel.latest_capture()
|
||||||
// Note: If a device hangs up, check that this conditional is passing correctly, as there is
|
|
||||||
// no time-out checks here in the interest of execution speed.
|
|
||||||
while !self.transfer.get_transfer_complete_flag() {}
|
|
||||||
|
|
||||||
let next_buffer = self.next_buffer.take().unwrap();
|
|
||||||
|
|
||||||
// Start the next transfer.
|
|
||||||
let (prev_buffer, _, _) =
|
|
||||||
self.transfer.next_transfer(next_buffer).unwrap();
|
|
||||||
|
|
||||||
self.next_buffer.replace(prev_buffer); // .unwrap_none() https://github.com/rust-lang/rust/issues/62633
|
|
||||||
|
|
||||||
self.next_buffer.as_ref().unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user