Revert "pounder timestmper: don't use DMA"
This reverts commit 26b261364f
.
First needs to reduce capture rate to batch interval. Otherwise it's
jittery due to polling alignment.
This commit is contained in:
parent
26b261364f
commit
d97ee3f0c4
@ -233,6 +233,11 @@ 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
|
||||||
@ -941,6 +946,7 @@ 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,12 +24,27 @@
|
|||||||
///! schedule.
|
///! schedule.
|
||||||
use stm32h7xx_hal as hal;
|
use stm32h7xx_hal as hal;
|
||||||
|
|
||||||
use crate::hardware::timers;
|
use hal::dma::{dma::DmaConfig, PeripheralToMemory, Transfer};
|
||||||
|
|
||||||
|
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,
|
||||||
capture_channel: timers::tim8::Channel1InputCapture,
|
transfer: Transfer<
|
||||||
|
hal::dma::dma::Stream0<hal::stm32::DMA2>,
|
||||||
|
timers::tim8::Channel1InputCapture,
|
||||||
|
PeripheralToMemory,
|
||||||
|
&'static mut [u16; SAMPLE_BUFFER_SIZE],
|
||||||
|
hal::dma::DBTransfer,
|
||||||
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Timestamper {
|
impl Timestamper {
|
||||||
@ -50,12 +65,18 @@ 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);
|
||||||
|
|
||||||
@ -66,29 +87,62 @@ 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,
|
||||||
capture_channel: input_capture,
|
transfer: data_transfer,
|
||||||
|
|
||||||
|
// 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 collecting timestamps.
|
/// Start the DMA transfer for collecting timestamps.
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn start(&mut self) {
|
pub fn start(&mut self) {
|
||||||
self.capture_channel.enable();
|
self.transfer
|
||||||
|
.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 timestamp.
|
/// Obtain a buffer filled with timestamps.
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// A `Result` potentially indicating capture overflow and containing a `Option` of a captured
|
/// A reference to the underlying buffer that has been filled with timestamps.
|
||||||
/// timestamp.
|
#[allow(dead_code)]
|
||||||
pub fn latest_timestamp(&mut self) -> Result<Option<u16>, Option<u16>> {
|
pub fn acquire_buffer(&mut self) -> &[u16; SAMPLE_BUFFER_SIZE] {
|
||||||
self.capture_channel.latest_capture()
|
// Wait for the transfer to fully complete before continuing.
|
||||||
|
// 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