Refactoring timer timestamping
This commit is contained in:
parent
fc81c8b5d8
commit
ec046bc42d
12
src/adc.rs
12
src/adc.rs
|
@ -14,8 +14,8 @@
|
|||
///! both transfers are completed before reading the data. This is usually not significant for
|
||||
///! busy-waiting because the transfers should complete at approximately the same time.
|
||||
use super::{
|
||||
hal, sampling_timer, DMAReq, DmaConfig, MemoryToPeripheral,
|
||||
PeripheralToMemory, Priority, TargetAddress, Transfer, SAMPLE_BUFFER_SIZE,
|
||||
hal, timers, DMAReq, DmaConfig, MemoryToPeripheral, PeripheralToMemory,
|
||||
Priority, TargetAddress, Transfer, SAMPLE_BUFFER_SIZE,
|
||||
};
|
||||
|
||||
// The following data is written by the timer ADC sample trigger into each of the SPI TXFIFOs. Note
|
||||
|
@ -38,12 +38,10 @@ macro_rules! adc_input {
|
|||
/// $spi is used as a type for indicating a DMA transfer into the SPI TX FIFO
|
||||
/// whenever the tim2 update dma request occurs.
|
||||
struct $spi {
|
||||
_channel: sampling_timer::tim2::$trigger_channel,
|
||||
_channel: timers::tim2::$trigger_channel,
|
||||
}
|
||||
impl $spi {
|
||||
pub fn new(
|
||||
_channel: sampling_timer::tim2::$trigger_channel,
|
||||
) -> Self {
|
||||
pub fn new(_channel: timers::tim2::$trigger_channel) -> Self {
|
||||
Self { _channel }
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +98,7 @@ macro_rules! adc_input {
|
|||
hal::stm32::DMA1,
|
||||
>,
|
||||
data_stream: hal::dma::dma::$data_stream<hal::stm32::DMA1>,
|
||||
trigger_channel: sampling_timer::tim2::$trigger_channel,
|
||||
trigger_channel: timers::tim2::$trigger_channel,
|
||||
) -> Self {
|
||||
// Generate DMA events when an output compare of the timer hitting zero (timer roll over)
|
||||
// occurs.
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
///! configured to generate a DMA write into the SPI TXFIFO, which initiates a SPI transfer and
|
||||
///! results in DAC update for both channels.
|
||||
use super::{
|
||||
hal, sampling_timer, DMAReq, DmaConfig, MemoryToPeripheral, TargetAddress,
|
||||
hal, timers, DMAReq, DmaConfig, MemoryToPeripheral, TargetAddress,
|
||||
Transfer, SAMPLE_BUFFER_SIZE,
|
||||
};
|
||||
|
||||
|
@ -22,12 +22,12 @@ macro_rules! dac_output {
|
|||
/// $spi is used as a type for indicating a DMA transfer into the SPI TX FIFO
|
||||
struct $spi {
|
||||
spi: hal::spi::Spi<hal::stm32::$spi, hal::spi::Disabled, u16>,
|
||||
_channel: sampling_timer::tim2::$trigger_channel,
|
||||
_channel: timers::tim2::$trigger_channel,
|
||||
}
|
||||
|
||||
impl $spi {
|
||||
pub fn new(
|
||||
_channel: sampling_timer::tim2::$trigger_channel,
|
||||
_channel: timers::tim2::$trigger_channel,
|
||||
spi: hal::spi::Spi<hal::stm32::$spi, hal::spi::Disabled, u16>,
|
||||
) -> Self {
|
||||
Self { _channel, spi }
|
||||
|
@ -73,7 +73,7 @@ macro_rules! dac_output {
|
|||
pub fn new(
|
||||
spi: hal::spi::Spi<hal::stm32::$spi, hal::spi::Enabled, u16>,
|
||||
stream: hal::dma::dma::$data_stream<hal::stm32::DMA1>,
|
||||
trigger_channel: sampling_timer::tim2::$trigger_channel,
|
||||
trigger_channel: timers::tim2::$trigger_channel,
|
||||
) -> Self {
|
||||
// Generate DMA events when an output compare of the timer hitting zero (timer roll over)
|
||||
// occurs.
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
use super::{hal, sampling_timer, DmaConfig, PeripheralToMemory, Transfer};
|
||||
use super::{hal, timers, DmaConfig, PeripheralToMemory, Transfer};
|
||||
|
||||
const INPUT_BUFFER_SIZE: usize = 1;
|
||||
|
||||
#[link_section = ".axisram.buffers"]
|
||||
static mut BUF0: [u16; INPUT_BUFFER_SIZE] = [0; INPUT_BUFFER_SIZE];
|
||||
|
||||
#[link_section = ".axisram.buffers"]
|
||||
static mut BUF1: [u16; INPUT_BUFFER_SIZE] = [0; INPUT_BUFFER_SIZE];
|
||||
static mut BUF: [[u16; INPUT_BUFFER_SIZE]; 2] = [[0; INPUT_BUFFER_SIZE]; 2];
|
||||
|
||||
pub struct InputStamper {
|
||||
_di0_trigger: hal::gpio::gpioa::PA3<hal::gpio::Alternate<hal::gpio::AF1>>,
|
||||
_di0_trigger: hal::gpio::gpioa::PA3<hal::gpio::Alternate<hal::gpio::AF2>>,
|
||||
timestamp_buffer: heapless::Vec<u16, heapless::consts::U128>,
|
||||
next_buffer: Option<&'static mut [u16; INPUT_BUFFER_SIZE]>,
|
||||
transfer: Transfer<
|
||||
hal::dma::dma::Stream6<hal::stm32::DMA1>,
|
||||
sampling_timer::tim2::Channel4InputCapture,
|
||||
timers::tim5::Channel4InputCapture,
|
||||
PeripheralToMemory,
|
||||
&'static mut [u16; INPUT_BUFFER_SIZE],
|
||||
>,
|
||||
|
@ -22,17 +19,19 @@ pub struct InputStamper {
|
|||
|
||||
impl InputStamper {
|
||||
pub fn new(
|
||||
trigger: hal::gpio::gpioa::PA3<hal::gpio::Alternate<hal::gpio::AF1>>,
|
||||
trigger: hal::gpio::gpioa::PA3<hal::gpio::Alternate<hal::gpio::AF2>>,
|
||||
stream: hal::dma::dma::Stream6<hal::stm32::DMA1>,
|
||||
timer_channel: sampling_timer::tim2::Channel4,
|
||||
timer_channel: timers::tim5::Channel4,
|
||||
) -> Self {
|
||||
// Utilize the TIM2 CH4 as an input capture channel - use TI4 (the DI0 input trigger) as the
|
||||
// Utilize the TIM5 CH4 as an input capture channel - use TI4 (the DI0 input trigger) as the
|
||||
// capture source.
|
||||
timer_channel.listen_dma();
|
||||
let input_capture = timer_channel.to_input_capture(sampling_timer::tim2::CC4S_A::TI4);
|
||||
let input_capture =
|
||||
timer_channel.to_input_capture(timers::tim5::CC4S_A::TI4);
|
||||
|
||||
// Set up the DMA transfer.
|
||||
let dma_config = DmaConfig::default()
|
||||
.transfer_complete_interrupt(true)
|
||||
.memory_increment(true)
|
||||
.peripheral_increment(false);
|
||||
|
||||
|
@ -40,7 +39,7 @@ impl InputStamper {
|
|||
Transfer::init(
|
||||
stream,
|
||||
input_capture,
|
||||
unsafe { &mut BUF0 },
|
||||
unsafe { &mut BUF[0] },
|
||||
None,
|
||||
dma_config,
|
||||
);
|
||||
|
@ -49,7 +48,7 @@ impl InputStamper {
|
|||
|
||||
Self {
|
||||
timestamp_buffer: heapless::Vec::new(),
|
||||
next_buffer: unsafe { Some(&mut BUF1) },
|
||||
next_buffer: unsafe { Some(&mut BUF[1]) },
|
||||
transfer: timestamp_transfer,
|
||||
_di0_trigger: trigger,
|
||||
}
|
||||
|
|
36
src/main.rs
36
src/main.rs
|
@ -69,13 +69,13 @@ static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new();
|
|||
mod adc;
|
||||
mod afe;
|
||||
mod dac;
|
||||
mod digital_input_stamper;
|
||||
mod hrtimer;
|
||||
mod design_parameters;
|
||||
mod digital_input_stamper;
|
||||
mod eeprom;
|
||||
mod hrtimer;
|
||||
mod pounder;
|
||||
mod sampling_timer;
|
||||
mod server;
|
||||
mod timers;
|
||||
|
||||
use adc::{Adc0Input, Adc1Input};
|
||||
use dac::{Dac0Output, Dac1Output};
|
||||
|
@ -285,9 +285,22 @@ const APP: () = {
|
|||
&ccdr.clocks,
|
||||
);
|
||||
|
||||
let mut sampling_timer = sampling_timer::SamplingTimer::new(timer2);
|
||||
let mut sampling_timer = timers::SamplingTimer::new(timer2);
|
||||
let sampling_timer_channels = sampling_timer.channels();
|
||||
|
||||
let mut timestamp_timer = {
|
||||
// TODO: This needs to be precisely controlled via the prescaler of the timer.
|
||||
let timer5 = dp.TIM5.timer(
|
||||
(SAMPLE_FREQUENCY_KHZ / SAMPLE_BUFFER_SIZE as u32).khz(),
|
||||
ccdr.peripheral.TIM5,
|
||||
&ccdr.clocks,
|
||||
);
|
||||
|
||||
timers::TimestampTimer::new(timer5)
|
||||
};
|
||||
|
||||
let timestamp_timer_channels = timestamp_timer.channels();
|
||||
|
||||
// Configure the SPI interfaces to the ADCs and DACs.
|
||||
let adcs = {
|
||||
let adc0 = {
|
||||
|
@ -770,16 +783,17 @@ const APP: () = {
|
|||
cp.DWT.enable_cycle_counter();
|
||||
|
||||
let input_stamper = {
|
||||
let trigger = gpioa.pa3.into_alternate_af1();
|
||||
let trigger = gpioa.pa3.into_alternate_af2();
|
||||
digital_input_stamper::InputStamper::new(
|
||||
trigger,
|
||||
dma_streams.6,
|
||||
sampling_timer_channels.ch4,
|
||||
timestamp_timer_channels.ch4,
|
||||
)
|
||||
};
|
||||
|
||||
// Start sampling ADCs.
|
||||
sampling_timer.start();
|
||||
timestamp_timer.start();
|
||||
|
||||
init::LateResources {
|
||||
afes: (afe0, afe1),
|
||||
|
@ -797,11 +811,6 @@ const APP: () = {
|
|||
}
|
||||
}
|
||||
|
||||
#[task(binds=DMA1_STR6, resources=[input_stamper], priority = 2)]
|
||||
fn digital_stamper(c: digital_stamper::Context) {
|
||||
panic!("Timestamp overflow")
|
||||
}
|
||||
|
||||
#[task(binds=DMA1_STR3, resources=[adcs, dacs, iir_state, iir_ch], priority=2)]
|
||||
fn process(c: process::Context) {
|
||||
let adc_samples = [
|
||||
|
@ -833,6 +842,11 @@ const APP: () = {
|
|||
c.resources.dacs.1.release_buffer(dac1);
|
||||
}
|
||||
|
||||
#[task(binds=DMA1_STR6, priority = 2)]
|
||||
fn digital_stamper(_: digital_stamper::Context) {
|
||||
panic!("Timestamp overflow")
|
||||
}
|
||||
|
||||
#[idle(resources=[net_interface, pounder, mac_addr, eth_mac, iir_state, iir_ch, afes])]
|
||||
fn idle(mut c: idle::Context) -> ! {
|
||||
let mut socket_set_entries: [_; 8] = Default::default();
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
///! The sampling timer is used for managing ADC sampling and external reference timestamping.
|
||||
use super::hal;
|
||||
|
||||
macro_rules! timer_channels {
|
||||
($name:ident, $TY:ident) => {
|
||||
paste::paste! {
|
||||
|
||||
/// The timer used for managing ADC sampling.
|
||||
pub struct SamplingTimer {
|
||||
timer: hal::timer::Timer<hal::stm32::TIM2>,
|
||||
channels: Option<tim2::Channels>,
|
||||
pub struct $name {
|
||||
timer: hal::timer::Timer<hal::stm32::[< $TY >]>,
|
||||
channels: Option<[< $TY:lower >]::Channels>,
|
||||
}
|
||||
|
||||
impl SamplingTimer {
|
||||
impl $name {
|
||||
/// Construct the sampling timer.
|
||||
pub fn new(mut timer: hal::timer::Timer<hal::stm32::TIM2>) -> Self {
|
||||
pub fn new(mut timer: hal::timer::Timer<hal::stm32::[< $TY>]>) -> Self {
|
||||
timer.pause();
|
||||
|
||||
Self {
|
||||
|
@ -19,12 +23,12 @@ impl SamplingTimer {
|
|||
// provided through the associated channel structures. We additionally guarantee this
|
||||
// can only be called once because there is only one Timer2 and this resource takes
|
||||
// ownership of it once instantiated.
|
||||
channels: unsafe { Some(tim2::Channels::new()) },
|
||||
channels: unsafe { Some([< $TY:lower >]::Channels::new()) },
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the timer capture/compare channels.
|
||||
pub fn channels(&mut self) -> tim2::Channels {
|
||||
pub fn channels(&mut self) -> [< $TY:lower >]::Channels {
|
||||
self.channels.take().unwrap()
|
||||
}
|
||||
|
||||
|
@ -35,16 +39,13 @@ impl SamplingTimer {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! timer_channels {
|
||||
($TY:ty) => {
|
||||
paste::paste! {
|
||||
pub mod [< $TY:lower >] {
|
||||
pub use hal::stm32::[< $TY:lower >]::ccmr1_input::{CC1S_A, CC2S_A};
|
||||
pub use hal::stm32::[< $TY:lower >]::ccmr2_input::{CC3S_A, CC4S_A};
|
||||
pub use hal::stm32::tim2::ccmr1_input::{CC1S_A, CC2S_A};
|
||||
pub use hal::stm32::tim2::ccmr2_input::{CC3S_A, CC4S_A};
|
||||
|
||||
use stm32h7xx_hal as hal;
|
||||
use hal::dma::{traits::TargetAddress, PeripheralToMemory, dma::DMAReq};
|
||||
use hal::stm32::TIM2;
|
||||
use hal::stm32::$TY;
|
||||
|
||||
/// The channels representing the timer.
|
||||
pub struct Channels {
|
||||
|
@ -92,6 +93,7 @@ macro_rules! timer_channels {
|
|||
}
|
||||
|
||||
/// Allow the channel to generate DMA requests.
|
||||
#[allow(dead_code)]
|
||||
pub fn listen_dma(&self) {
|
||||
let regs = unsafe { &*<$TY>::ptr() };
|
||||
regs.dier.modify(|_, w| w.[< cc $index de >]().set_bit());
|
||||
|
@ -101,6 +103,7 @@ macro_rules! timer_channels {
|
|||
///
|
||||
/// # Args
|
||||
/// * `value` - The value to compare the sampling timer's counter against.
|
||||
#[allow(dead_code)]
|
||||
pub fn to_output_compare(&self, value: u32) {
|
||||
let regs = unsafe { &*<$TY>::ptr() };
|
||||
assert!(value <= regs.arr.read().bits());
|
||||
|
@ -113,7 +116,8 @@ macro_rules! timer_channels {
|
|||
///
|
||||
/// # Args
|
||||
/// * `input` - The input source for the input capture event.
|
||||
pub fn to_input_capture(self, input: hal::stm32::[<$TY:lower>]::[< $ccmrx _input >]::[< CC $index S_A >]) -> [< Channel $index InputCapture >]{
|
||||
#[allow(dead_code)]
|
||||
pub fn to_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));
|
||||
|
||||
|
@ -135,4 +139,5 @@ macro_rules! timer_channels {
|
|||
};
|
||||
}
|
||||
|
||||
timer_channels!(TIM2);
|
||||
timer_channels!(SamplingTimer, TIM2);
|
||||
timer_channels!(TimestampTimer, TIM5);
|
Loading…
Reference in New Issue