diff --git a/Cargo.lock b/Cargo.lock index 9cf3a58..edc2864 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -517,7 +517,7 @@ dependencies = [ [[package]] name = "stm32h7xx-hal" version = "0.8.0" -source = "git+https://github.com/stm32-rs/stm32h7xx-hal?branch=dma#0bfeeca4ce120c1b7c6d140a7da73a4372b874d8" +source = "git+https://github.com/quartiq/stm32h7xx-hal?branch=feature/number-of-transfers#e70a78788e74be5281321213b53e8cd1d213550e" dependencies = [ "bare-metal 1.0.0", "cast", diff --git a/Cargo.toml b/Cargo.toml index 7217589..f1acbe0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,8 +53,8 @@ default-features = false [dependencies.stm32h7xx-hal] features = ["stm32h743v", "rt", "unproven", "ethernet", "quadspi"] -git = "https://github.com/stm32-rs/stm32h7xx-hal" -branch = "dma" +git = "https://github.com/quartiq/stm32h7xx-hal" +branch = "feature/number-of-transfers" [features] semihosting = ["panic-semihosting", "cortex-m-log/semihosting"] diff --git a/src/adc.rs b/src/adc.rs index e9120aa..4017f7f 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -195,7 +195,7 @@ macro_rules! adc_input { // Start the next transfer. self.transfer.clear_interrupts(); - let (prev_buffer, _) = + 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 diff --git a/src/dac.rs b/src/dac.rs index d96109c..00c24d4 100644 --- a/src/dac.rs +++ b/src/dac.rs @@ -143,7 +143,7 @@ macro_rules! dac_output { // Start the next transfer. self.transfer.clear_interrupts(); - let (prev_buffer, _) = + let (prev_buffer, _, _) = self.transfer.next_transfer(next_buffer).unwrap(); // .unwrap_none() https://github.com/rust-lang/rust/issues/62633 diff --git a/src/digital_input_stamper.rs b/src/digital_input_stamper.rs index 88b1c58..71cd5b1 100644 --- a/src/digital_input_stamper.rs +++ b/src/digital_input_stamper.rs @@ -13,8 +13,8 @@ pub struct InputStamper { timestamp_buffer: heapless::Vec, next_buffer: Option<&'static mut [u16; INPUT_BUFFER_SIZE]>, transfer: Transfer< - hal::dma::dma::Stream4, - sampling_timer::Timer2Channel4, + hal::dma::dma::Stream6, + sampling_timer::tim2::Channel4InputCapture, PeripheralToMemory, &'static mut [u16; INPUT_BUFFER_SIZE], >, @@ -23,13 +23,13 @@ pub struct InputStamper { impl InputStamper { pub fn new( trigger: hal::gpio::gpioa::PA3>, - stream: hal::dma::dma::Stream4, - timer_channel: sampling_timer::Timer2Channel4, + stream: hal::dma::dma::Stream6, + timer_channel: sampling_timer::tim2::Channel4, ) -> Self { // Utilize the TIM2 CH4 as an input capture channel - use TI4 (the DI0 input trigger) as the // capture source. timer_channel.listen_dma(); - timer_channel.to_input_capture(sampling_timer::CC4S_A::TI4); + let input_capture = timer_channel.to_input_capture(sampling_timer::tim2::CC4S_A::TI4); // Set up the DMA transfer. let dma_config = DmaConfig::default() @@ -39,7 +39,7 @@ impl InputStamper { let mut timestamp_transfer: Transfer<_, _, PeripheralToMemory, _> = Transfer::init( stream, - timer_channel, + input_capture, unsafe { &mut BUF0 }, None, dma_config, diff --git a/src/main.rs b/src/main.rs index 453e8ab..f168c95 100644 --- a/src/main.rs +++ b/src/main.rs @@ -70,9 +70,7 @@ mod adc; mod afe; mod dac; mod digital_input_stamper; -mod eeprom; mod hrtimer; -mod iir; mod design_parameters; mod eeprom; mod pounder; @@ -775,7 +773,7 @@ const APP: () = { let trigger = gpioa.pa3.into_alternate_af1(); digital_input_stamper::InputStamper::new( trigger, - dma_streams.4, + dma_streams.6, sampling_timer_channels.ch4, ) }; @@ -796,14 +794,12 @@ const APP: () = { net_interface: network_interface, eth_mac, mac_addr, - - profiles: heapless::spsc::Queue::new(), } } - #[task(binds=DMA1_STR4, resources=[input_stamper], priority = 2)] + #[task(binds=DMA1_STR6, resources=[input_stamper], priority = 2)] fn digital_stamper(c: digital_stamper::Context) { - let _timestamps = c.resources.input_stamper.transfer_complete_handler(); + panic!("Timestamp overflow") } #[task(binds=DMA1_STR3, resources=[adcs, dacs, iir_state, iir_ch], priority=2)] @@ -911,44 +907,7 @@ const APP: () = { Ok::(state) }), "stabilizer/afe0/gain": (|| c.resources.afes.0.get_gain()), - "stabilizer/afe1/gain": (|| c.resources.afes.1.get_gain()), - "pounder/in0": (|| { - match c.resources.pounder { - Some(pounder) => - pounder.get_input_channel_state(pounder::Channel::In0), - _ => Err(pounder::Error::Access), - } - }), - "pounder/in1": (|| { - match c.resources.pounder { - Some(pounder) => - pounder.get_input_channel_state(pounder::Channel::In1), - _ => Err(pounder::Error::Access), - } - }), - "pounder/out0": (|| { - match c.resources.pounder { - Some(pounder) => - pounder.get_output_channel_state(pounder::Channel::Out0), - _ => Err(pounder::Error::Access), - } - }), - "pounder/out1": (|| { - match c.resources.pounder { - Some(pounder) => - pounder.get_output_channel_state(pounder::Channel::Out1), - _ => Err(pounder::Error::Access), - } - }), ->>>>>>> master - "pounder/dds/clock": (|| { - c.resources.pounder.lock(|pounder| { - match pounder { - Some(pounder) => pounder.get_dds_clock_config(), - _ => Err(pounder::Error::Access), - } - }) - }) + "stabilizer/afe1/gain": (|| c.resources.afes.1.get_gain()) ], modifiable_attributes: [ @@ -996,50 +955,6 @@ const APP: () = { Ok::(req) }) }), - "pounder/in0": pounder::ChannelState, (|state| { - c.resources.pounder.lock(|pounder| { - match pounder { - Some(pounder) => - pounder.set_channel_state(pounder::Channel::In0, state), - _ => Err(pounder::Error::Access), - } - }) - }), - "pounder/in1": pounder::ChannelState, (|state| { - c.resources.pounder.lock(|pounder| { - match pounder { - Some(pounder) => - pounder.set_channel_state(pounder::Channel::In1, state), - _ => Err(pounder::Error::Access), - } - }) - }), - "pounder/out0": pounder::ChannelState, (|state| { - c.resources.pounder.lock(|pounder| { - match pounder { - Some(pounder) => - pounder.set_channel_state(pounder::Channel::Out0, state), - _ => Err(pounder::Error::Access), - } - }) - }), - "pounder/out1": pounder::ChannelState, (|state| { - c.resources.pounder.lock(|pounder| { - match pounder { - Some(pounder) => - pounder.set_channel_state(pounder::Channel::Out1, state), - _ => Err(pounder::Error::Access), - } - }) - }), - "pounder/dds/clock": pounder::DdsClockConfig, (|config| { - c.resources.pounder.lock(|pounder| { - match pounder { - Some(pounder) => pounder.configure_dds_clock(config), - _ => Err(pounder::Error::Access), - } - }) - }), "stabilizer/afe0/gain": afe::Gain, (|gain| { c.resources.afes.0.set_gain(gain); Ok::<(), ()>(()) diff --git a/src/sampling_timer.rs b/src/sampling_timer.rs index b7f9480..3218996 100644 --- a/src/sampling_timer.rs +++ b/src/sampling_timer.rs @@ -1,6 +1,5 @@ ///! The sampling timer is used for managing ADC sampling and external reference timestamping. use super::hal; -pub use hal::stm32::tim2::ccmr2_input::CC4S_A; /// The timer used for managing ADC sampling. pub struct SamplingTimer { @@ -36,12 +35,54 @@ impl SamplingTimer { } } -macro_rules! timer_channel { - ($name:ident, $TY:ty, ($ccxde:expr, $ccrx:expr, $ccmrx_output:expr, $ccxs:expr)) => { - pub struct $name {} - +macro_rules! timer_channels { + ($TY:ty) => { paste::paste! { - impl $name { + 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}; + + use stm32h7xx_hal as hal; + use hal::dma::{traits::TargetAddress, PeripheralToMemory, dma::DMAReq}; + use hal::stm32::TIM2; + + /// The channels representing the timer. + pub struct Channels { + pub ch1: Channel1, + pub ch2: Channel2, + pub ch3: Channel3, + pub ch4: Channel4, + } + + impl Channels { + /// Construct a new set of channels. + /// + /// Note(unsafe): This is only safe to call once. + pub unsafe fn new() -> Self { + Self { + ch1: Channel1::new(), + ch2: Channel2::new(), + ch3: Channel3::new(), + ch4: Channel4::new(), + } + } + } + + timer_channels!(1, $TY, ccmr1); + timer_channels!(2, $TY, ccmr1); + timer_channels!(3, $TY, ccmr2); + timer_channels!(4, $TY, ccmr2); + } + } + }; + + ($index:expr, $TY:ty, $ccmrx:expr) => { + paste::paste! { + pub struct [< Channel $index >] {} + + pub struct [< Channel $index InputCapture>] {} + + impl [< Channel $index >] { /// Construct a new timer channel. /// /// Note(unsafe): This function must only be called once. Once constructed, the @@ -50,71 +91,48 @@ macro_rules! timer_channel { Self {} } - /// Allow CH4 to generate DMA requests. + /// Allow the channel to generate DMA requests. pub fn listen_dma(&self) { let regs = unsafe { &*<$TY>::ptr() }; - regs.dier.modify(|_, w| w.[< $ccxde >]().set_bit()); + regs.dier.modify(|_, w| w.[< cc $index de >]().set_bit()); } - /// Operate CH2 as an output-compare. + /// Operate the channel as an output-compare. /// /// # Args /// * `value` - The value to compare the sampling timer's counter against. pub fn to_output_compare(&self, value: u32) { let regs = unsafe { &*<$TY>::ptr() }; assert!(value <= regs.arr.read().bits()); - regs.[< $ccrx >].write(|w| w.ccr().bits(value)); - regs.[< $ccmrx_output >]() - .modify(|_, w| unsafe { w.[< $ccxs >]().bits(0) }); + regs.[< ccr $index >].write(|w| w.ccr().bits(value)); + regs.[< $ccmrx _output >]() + .modify(|_, w| unsafe { w.[< cc $index s >]().bits(0) }); + } + + /// Operate the channel in input-capture mode. + /// + /// # 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 >]{ + let regs = unsafe { &*<$TY>::ptr() }; + regs.[< $ccmrx _input >]().modify(|_, w| w.[< cc $index s>]().variant(input)); + + [< Channel $index InputCapture >] {} + } + } + + unsafe impl TargetAddress for [< Channel $index InputCapture >] { + type MemSize = u16; + + const REQUEST_LINE: Option = Some(DMAReq::[< $TY _CH $index >]as u8); + + fn address(&self) -> u32 { + let regs = unsafe { &*<$TY>::ptr() }; + ®s.[] as *const _ as u32 } } } }; } -pub mod tim2 { - use stm32h7xx_hal as hal; - - /// The channels representing the timer. - pub struct Channels { - pub ch1: Channel1, - pub ch2: Channel2, - pub ch3: Channel3, - pub ch4: Channel4, - } - - impl Channels { - /// Construct a new set of channels. - /// - /// Note(unsafe): This is only safe to call once. - pub unsafe fn new() -> Self { - Self { - ch1: Channel1::new(), - ch2: Channel2::new(), - ch3: Channel3::new(), - ch4: Channel4::new(), - } - } - } - - timer_channel!( - Channel1, - hal::stm32::TIM2, - (cc1de, ccr1, ccmr1_output, cc1s) - ); - timer_channel!( - Channel2, - hal::stm32::TIM2, - (cc2de, ccr2, ccmr1_output, cc1s) - ); - timer_channel!( - Channel3, - hal::stm32::TIM2, - (cc3de, ccr3, ccmr2_output, cc3s) - ); - timer_channel!( - Channel4, - hal::stm32::TIM2, - (cc4de, ccr4, ccmr2_output, cc4s) - ); -} +timer_channels!(TIM2);