Adding precise control of timer periods and prescalers
This commit is contained in:
parent
a134340726
commit
1a1d8fd8b9
|
@ -4,3 +4,6 @@ pub const ADC_SETUP_TIME: f32 = 220e-9;
|
||||||
|
|
||||||
/// The maximum DAC/ADC serial clock line frequency. This is a hardware limit.
|
/// 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_MHZ_MAX: u32 = 50;
|
||||||
|
|
||||||
|
/// The optimal counting frequency of the hardware timers used for timestamping and sampling.
|
||||||
|
pub const TIMER_FREQUENCY_MHZ: u32 = 100;
|
||||||
|
|
61
src/main.rs
61
src/main.rs
|
@ -30,6 +30,8 @@ extern crate panic_halt;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
|
use core::convert::TryInto;
|
||||||
|
|
||||||
// use core::sync::atomic::{AtomicU32, AtomicBool, Ordering};
|
// use core::sync::atomic::{AtomicU32, AtomicBool, Ordering};
|
||||||
use cortex_m_rt::exception;
|
use cortex_m_rt::exception;
|
||||||
use rtic::cyccnt::{Instant, U32Ext};
|
use rtic::cyccnt::{Instant, U32Ext};
|
||||||
|
@ -54,11 +56,12 @@ use smoltcp::wire::Ipv4Address;
|
||||||
|
|
||||||
use heapless::{consts::*, String};
|
use heapless::{consts::*, String};
|
||||||
|
|
||||||
// The desired sampling frequency of the ADCs.
|
// The number of ticks in the ADC sampling timer. The timer runs at 100MHz, so the step size is
|
||||||
const SAMPLE_FREQUENCY_KHZ: u32 = 500;
|
// equal to 10ns per tick.
|
||||||
|
const ADC_SAMPLE_TICKS: u32 = 128;
|
||||||
|
|
||||||
// The desired ADC sample processing buffer size.
|
// The desired ADC sample processing buffer size.
|
||||||
const SAMPLE_BUFFER_SIZE: usize = 1;
|
const SAMPLE_BUFFER_SIZE: usize = 8;
|
||||||
|
|
||||||
// The number of cascaded IIR biquads per channel. Select 1 or 2!
|
// The number of cascaded IIR biquads per channel. Select 1 or 2!
|
||||||
const IIR_CASCADE_LENGTH: usize = 1;
|
const IIR_CASCADE_LENGTH: usize = 1;
|
||||||
|
@ -282,29 +285,51 @@ const APP: () = {
|
||||||
hal::dma::dma::StreamsTuple::new(dp.DMA1, ccdr.peripheral.DMA1);
|
hal::dma::dma::StreamsTuple::new(dp.DMA1, ccdr.peripheral.DMA1);
|
||||||
|
|
||||||
// Configure timer 2 to trigger conversions for the ADC
|
// Configure timer 2 to trigger conversions for the ADC
|
||||||
let timer2 = dp.TIM2.timer(
|
let mut sampling_timer = {
|
||||||
SAMPLE_FREQUENCY_KHZ.khz(),
|
// The timer frequency is manually adjusted below, so the 1KHz setting here is a
|
||||||
ccdr.peripheral.TIM2,
|
// dont-care.
|
||||||
&ccdr.clocks,
|
let mut timer2 =
|
||||||
);
|
dp.TIM2.timer(1.khz(), ccdr.peripheral.TIM2, &ccdr.clocks);
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
|
||||||
let mut sampling_timer = timers::SamplingTimer::new(timer2);
|
let mut sampling_timer = timers::SamplingTimer::new(timer2);
|
||||||
|
sampling_timer.set_period(ADC_SAMPLE_TICKS - 1);
|
||||||
|
|
||||||
|
sampling_timer
|
||||||
|
};
|
||||||
|
|
||||||
let sampling_timer_channels = sampling_timer.channels();
|
let sampling_timer_channels = sampling_timer.channels();
|
||||||
|
|
||||||
let mut timestamp_timer = {
|
let mut timestamp_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
|
||||||
// dont-care.
|
// dont-care.
|
||||||
let timer5 =
|
let mut timer5 =
|
||||||
dp.TIM5.timer(1.khz(), ccdr.peripheral.TIM5, &ccdr.clocks);
|
dp.TIM5.timer(1.khz(), ccdr.peripheral.TIM5, &ccdr.clocks);
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
|
||||||
// The time stamp timer must run at exactly a multiple of the sample timer based on the
|
// 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
|
// batch size. To accomodate this, we manually set the period identical to the sample
|
||||||
// timer, but use a prescaler that is `BATCH_SIZE` longer.
|
// timer, but use a prescaler that is `BATCH_SIZE` longer.
|
||||||
let mut timer = timers::TimestampTimer::new(timer5);
|
let mut timer = timers::TimestampTimer::new(timer5);
|
||||||
timer.set_period(sampling_timer.get_period());
|
|
||||||
timer.set_prescaler(
|
let period: u32 = {
|
||||||
sampling_timer.get_prescaler() * SAMPLE_BUFFER_SIZE as u16,
|
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;
|
||||||
|
let period: u64 = batch_duration * batches_per_overflow - 1u64;
|
||||||
|
period.try_into().unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
timer.set_period(period);
|
||||||
|
|
||||||
timer
|
timer
|
||||||
};
|
};
|
||||||
|
@ -667,9 +692,13 @@ const APP: () = {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Ensure that we have enough time for an IO-update every sample.
|
// Ensure that we have enough time for an IO-update every sample.
|
||||||
assert!(
|
let sample_frequency =
|
||||||
1.0 / (1000 * SAMPLE_FREQUENCY_KHZ) as f32 > 900_e-9
|
(design_parameters::TIMER_FREQUENCY_MHZ as f32
|
||||||
);
|
* 1_000_000.0)
|
||||||
|
/ ADC_SAMPLE_TICKS as f32;
|
||||||
|
|
||||||
|
let sample_period = 1.0 / sample_frequency;
|
||||||
|
assert!(sample_period > 900_e-9);
|
||||||
|
|
||||||
hrtimer
|
hrtimer
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue