Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: HRTIM #96

Closed
wants to merge 58 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
224f0d5
WIP
usbalbin May 9, 2023
58f44f3
Untested sort of maybe working chaos
usbalbin May 20, 2023
108c7b3
Dual channel support and cargo fmt
usbalbin May 20, 2023
ec9ec6f
Almost...
usbalbin May 20, 2023
af66e36
Still untested but might actually work, maybe
usbalbin May 20, 2023
7e1a45c
Adjust doc
usbalbin May 20, 2023
b56e2fd
Enable outputs in example
usbalbin May 20, 2023
f2de47f
Further cleanup
usbalbin May 20, 2023
a5e7f3a
Tested and verified on NUCLEO-G474RE
usbalbin Jun 7, 2023
2dcae09
hrtim_simple also tested and verified on NUCLEO-G474RE
usbalbin Jun 7, 2023
db94990
Hrtim cleanup, add pins for all timers but HRTIM_TIMF
usbalbin Jun 9, 2023
e059464
Several changes and fixes
usbalbin Jun 20, 2023
ec58b83
Start work on hrtim fault
usbalbin Jun 12, 2023
68feb9f
Add hrtim fault example
usbalbin Jun 20, 2023
ce22d9c
TOO MANY CHANGES
usbalbin Jun 28, 2023
688a867
Add ADC triggers among a lot of things to hrtim
usbalbin Aug 25, 2023
fccd37b
Disable push pull
usbalbin Aug 25, 2023
86b7cef
NOT DONE - Losts of hrtim stuff
usbalbin Sep 4, 2023
a5ea91f
Multiple hrtim changes
usbalbin Oct 24, 2023
7ddac7b
HRTIM: Fix bad pin mapping
usbalbin Oct 24, 2023
b615f95
HRTIM - Rework EventSource system and add deadtime support
usbalbin Oct 24, 2023
f89dee3
HRTIM refactor
usbalbin Nov 3, 2023
6c3d60d
More hrtim refactor
usbalbin Nov 4, 2023
76b2125
EEV
usbalbin Nov 5, 2023
83706b3
More work on hrtim eev
usbalbin Nov 6, 2023
35bff4f
even more eev hrtim
usbalbin Nov 6, 2023
916a422
more eev hrtim
usbalbin Nov 7, 2023
291014e
Update hrtim examples. TODO: Make sure timers are started
usbalbin Nov 8, 2023
741a4db
HRTIM examples
usbalbin Nov 8, 2023
1942ca7
Fix warnings for hrtim
usbalbin Nov 8, 2023
2217a97
HRTIM - Traitify adc_triggers
usbalbin Jan 6, 2024
4213ce0
HRTIM: Start work on capture support
usbalbin Jan 17, 2024
0350eb0
HRTIM: Add capture.rs
usbalbin Jan 18, 2024
20205c7
HRTIM: Impl CompareEvent for more types
usbalbin Jan 18, 2024
5a846ef
Fmt
usbalbin Jan 18, 2024
5dd9335
HRTIM: Traitify events
usbalbin Jan 18, 2024
e089ce5
HRTIM: Fix bugs caused by traitification
usbalbin Jan 19, 2024
a6ed404
HRTIM: Update adc-trigger example for traitification changes
usbalbin Jan 19, 2024
27075e1
HRTIM: Start timer and set trigger points in adc-trigger example
usbalbin Jan 19, 2024
b7bacde
HRTIM: Refactor adc trigger
usbalbin Jan 19, 2024
0e763b9
HRTIM: Refactor adc trigger - example hrtim-adc-trigger
usbalbin Jan 19, 2024
1626954
HRTIM: adc trigger impl into
usbalbin Jan 19, 2024
944985b
HRTIM: adc-trigger example set duty
usbalbin Jan 19, 2024
eb075b0
HRTIM: Move clear_repetition_interrupt to trait
usbalbin Jan 19, 2024
ab4c3b5
HRTIM: Capture interrupts and clippy
usbalbin Jan 22, 2024
8a7e208
HRTIM: Capture example
usbalbin Jan 22, 2024
a823f21
HRTIM: Create feature for all devices supporting hrtim
usbalbin Jan 22, 2024
2924811
HRTIM: Some fixes for capture example
usbalbin Jan 22, 2024
6e1d446
HRTIM: Fix warning in capture example
usbalbin Jan 22, 2024
b97dada
HRTIM: Add forgotten traitification impls
usbalbin Jan 22, 2024
749c064
HRTIM: Update examples
usbalbin Jan 22, 2024
47d7a43
HRTIM: Capture cleanup
usbalbin Jan 23, 2024
6887958
HRTIM: Avoid unneeded type parameters on HrTimer trait
usbalbin Jan 24, 2024
5ba64f8
HRTIM: Move some inherent methods to traits on HrTim
usbalbin Jan 24, 2024
066f4a3
HRTIM - Add derives for some types
usbalbin Apr 18, 2024
8ebf645
HRTIM - Allow using capture module with DMA
usbalbin Apr 19, 2024
6c619a9
HRTIM - Fix example
usbalbin Apr 19, 2024
f8018d1
HRTIM - Prevent future dataraces for DMA
usbalbin Apr 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 48 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,12 @@ stm32g431 = ["stm32g4/stm32g431"]
stm32g441 = ["stm32g4/stm32g441"]
stm32g471 = ["stm32g4/stm32g471"]
stm32g473 = ["stm32g4/stm32g473"]
stm32g474 = ["stm32g4/stm32g474"]
stm32g474 = ["stm32g4/stm32g474", "hrtim"]
stm32g483 = ["stm32g4/stm32g483"]
stm32g484 = ["stm32g4/stm32g484"]
stm32g484 = ["stm32g4/stm32g484", "hrtim"]
stm32g491 = ["stm32g4/stm32g491"]
stm32g4a1 = ["stm32g4/stm32g4a1"]
hrtim = []
log-itm = ["cortex-m-log/itm"]
log-rtt = []
log-semihost = ["cortex-m-log/semihosting"]
Expand All @@ -105,3 +106,48 @@ lto = true
[[example]]
name = "flash_with_rtic"
required-features = ["stm32g474"]

[[example]]
name = "hrtim-adc-trigger"
required-features = ["hrtim"]
path = "examples/hrtim/adc-trigger.rs"

[[example]]
name = "hrtim-capture"
required-features = ["hrtim"]
path = "examples/hrtim/capture.rs"

[[example]]
name = "hrtim-eev-comp"
required-features = ["hrtim"]
path = "examples/hrtim/eev-comp.rs"

[[example]]
name = "hrtim-eev"
required-features = ["hrtim"]
path = "examples/hrtim/eev.rs"

[[example]]
name = "hrtim-flt-comp"
required-features = ["hrtim"]
path = "examples/hrtim/flt-comp.rs"

[[example]]
name = "hrtim-flt"
required-features = ["hrtim"]
path = "examples/hrtim/flt.rs"

[[example]]
name = "hrtim"
required-features = ["hrtim"]
path = "examples/hrtim/hrtim.rs"

[[example]]
name = "hrtim-master"
required-features = ["hrtim"]
path = "examples/hrtim/master.rs"

[[example]]
name = "hrtim-simple"
required-features = ["hrtim"]
path = "examples/hrtim/simple.rs"
2 changes: 1 addition & 1 deletion examples/adc-one-shot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use stm32g4xx_hal as hal;

use cortex_m_rt::entry;

use log::info;
use utils::logger::info;

#[macro_use]
mod utils;
Expand Down
161 changes: 161 additions & 0 deletions examples/hrtim/adc-trigger.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
#![no_std]
#![no_main]

/// Example showcasing the use of the HRTIM peripheral to trigger the ADC at various points of the switch cycle off HRTIM_TIMA

#[path = "../utils/mod.rs"]
mod utils;

use cortex_m_rt::entry;

use defmt_rtt as _; // global logger
use panic_probe as _;

use utils::logger::info;

#[entry]
fn main() -> ! {
use hal::adc;
use stm32g4xx_hal as hal;

use hal::{
adc::{
config::{Continuous, Dma as AdcDma, SampleTime, Sequence},
AdcClaim, ClockSource, Temperature, Vref,
},
delay::SYSTDelayExt,
dma::{self, config::DmaConfig, stream::DMAExt, TransferExt},
gpio::{gpioa::PA8, gpioa::PA9, Alternate, GpioExt, AF13},
hrtim::compare_register::HrCompareRegister,
hrtim::control::HrControltExt,
hrtim::output::HrOutput,
hrtim::timer::HrTimer,
hrtim::HrPwmAdvExt,
hrtim::Pscl4,
pwr::PwrExt,
rcc::{self, RccExt},
stm32::Peripherals,
};

const VREF: f32 = 3.3;

info!("start");

let dp = Peripherals::take().unwrap();
let cp = cortex_m::Peripherals::take().expect("cannot take core peripherals");

// Set system frequency to 16MHz * 15/1/2 = 120MHz
// This would lead to HrTim running at 120MHz * 32 = 3.84...
info!("rcc");
let pwr = dp.PWR.constrain().freeze();
let mut rcc = dp.RCC.freeze(
rcc::Config::pll().pll_cfg(rcc::PllConfig {
mux: rcc::PLLSrc::HSI,
n: rcc::PllNMul::MUL_15,
m: rcc::PllMDiv::DIV_1,
r: Some(rcc::PllRDiv::DIV_2),

..Default::default()
}),
pwr,
);

let mut delay = cp.SYST.delay(&rcc.clocks);

let dma::stream::StreamsTuple(dma1ch1, ..) = dp.DMA1.split(&rcc);
let config = DmaConfig::default()
.transfer_complete_interrupt(true)
.circular_buffer(true)
.memory_increment(true);

info!("Setup Gpio");
let gpioa = dp.GPIOA.split(&mut rcc);
let pa0 = gpioa.pa0.into_analog();

let pin_a: PA8<Alternate<AF13>> = gpioa.pa8.into_alternate();
let pin_b: PA9<Alternate<AF13>> = gpioa.pa9.into_alternate();

// ...with a prescaler of 4 this gives us a HrTimer with a tick rate of 960MHz
// With max the max period set, this would be 960MHz/2^16 ~= 15kHz...
let prescaler = Pscl4;

// . .
// . 50% .
// ------ ------
//out1 | | | |
// | | | |
// -------- ---------- --------
// . ^ ^
// . | |
//AD samlp pa0 temp
let period = 0xFFFF;
let (hr_control, ..) = dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration();
let mut hr_control = hr_control.constrain();
let (mut timer, (mut cr1, _cr2, mut cr3, mut cr4), (mut out1, mut out2), ..) = dp
.HRTIM_TIMA
.pwm_advanced((pin_a, pin_b), &mut rcc)
.prescaler(prescaler)
.period(period)
.finalize(&mut hr_control);

cr1.set_duty(period / 2);
cr3.set_duty(period / 3);
cr4.set_duty((2 * u32::from(period) / 3) as u16);

hr_control.adc_trigger1.enable_source(&cr3);
hr_control.adc_trigger1.enable_source(&cr4);

out1.enable_rst_event(&cr1); // Set low on compare match with cr1
out2.enable_rst_event(&cr1);

out1.enable_set_event(&timer); // Set high at new period
out2.enable_set_event(&timer);

info!("Setup Adc1");
let mut adc = dp
.ADC1
.claim(ClockSource::SystemClock, &rcc, &mut delay, true);

adc.set_external_trigger((
adc::config::TriggerMode::RisingEdge,
&hr_control.adc_trigger1,
));
adc.enable_temperature(&dp.ADC12_COMMON);
adc.set_continuous(Continuous::Discontinuous);
adc.reset_sequence();
adc.configure_channel(&pa0, Sequence::One, SampleTime::Cycles_640_5);
adc.configure_channel(&Temperature, Sequence::Two, SampleTime::Cycles_640_5);

info!("Setup DMA");
let first_buffer = cortex_m::singleton!(: [u16; 10] = [0; 10]).unwrap();

let mut transfer = dma1ch1.into_circ_peripheral_to_memory_transfer(
adc.enable_dma(AdcDma::Continuous),
&mut first_buffer[..],
config,
);

transfer.start(|adc| adc.start_conversion());

out1.enable();
out2.enable();
usbalbin marked this conversation as resolved.
Show resolved Hide resolved

timer.start(&mut hr_control);

loop {
let mut b = [0_u16; 4];
let r = transfer.read_exact(&mut b);

info!("read: {}", r);
assert!(r == b.len());

let millivolts = Vref::sample_to_millivolts((b[0] + b[2]) / 2);
info!("pa3: {}mV", millivolts);
let temp = Temperature::temperature_to_degrees_centigrade(
(b[1] + b[3]) / 2,
VREF,
adc::config::Resolution::Twelve,
);
info!("temp: {}℃C", temp);
}
}
134 changes: 134 additions & 0 deletions examples/hrtim/capture-dma.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#![no_std]
#![no_main]

/// Example showcasing the use of the HRTIM peripheral's capture function to detect phase shift between a digital event and the output of HRTIM_TIMA

#[path = "../utils/mod.rs"]
mod utils;

use cortex_m_rt::entry;

use defmt_rtt as _; // global logger
use panic_probe as _;

use utils::logger::info;

#[entry]
fn main() -> ! {
use stm32g4xx_hal as hal;

use hal::{
dma::{config::DmaConfig, stream::DMAExt, TransferExt},
gpio::{gpioa::PA8, Alternate, GpioExt, AF13},
hrtim::{
capture, compare_register::HrCompareRegister, control::HrControltExt, external_event,
external_event::ToExternalEventSource, output::HrOutput, timer::HrSlaveTimerCpt,
timer::HrTimer, HrPwmAdvExt, Pscl128,
},
pwr::PwrExt,
rcc::{self, RccExt},
stm32::Peripherals,
};
use info;

info!("start");

let dp = Peripherals::take().unwrap();

// Set system frequency to 16MHz * 15/1/2 = 120MHz
// This would lead to HrTim running at 120MHz * 32 = 3.84...
info!("rcc");
let pwr = dp.PWR.constrain().freeze();
let mut rcc = dp.RCC.freeze(
rcc::Config::pll().pll_cfg(rcc::PllConfig {
mux: rcc::PLLSrc::HSI,
n: rcc::PllNMul::MUL_15,
m: rcc::PllMDiv::DIV_1,
r: Some(rcc::PllRDiv::DIV_2),

..Default::default()
}),
pwr,
);

info!("Setup Gpio");
let gpioa = dp.GPIOA.split(&mut rcc);
let gpiob = dp.GPIOB.split(&mut rcc);

// PA8 (D7 on Nucleo G474RE)
let pin_a: PA8<Alternate<AF13>> = gpioa.pa8.into_alternate();

// PB5 (D4 on Nucleo G474RE)
let input = gpiob.pb5.into_pull_down_input();

// ...with a prescaler of 128 this gives us a HrTimer with a tick rate of 30MHz
// With max the max period set, this would be 30MHz/2^16 ~= 458Hz...
let prescaler = Pscl128;

// t1 t2 .
// | | .
// v v .
// . .
// . 50% .
// ------ ------
//out1 | | | |
// | | | |
// -------- ---------- --------
let period = 0xFFFF;
let (mut hr_control, _flt_inputs, eev_inputs) =
dp.HRTIM_COMMON.hr_control(&mut rcc).wait_for_calibration();

let eev_input6 = eev_inputs
.eev_input6
.bind(input)
.edge_or_polarity(external_event::EdgeOrPolarity::Edge(
external_event::Edge::Both,
))
.finalize(&mut hr_control);

let mut hr_control = hr_control.constrain();
let (timer, (mut cr1, _cr2, _cr3, _cr4), mut out1, dma_ch) = dp
.HRTIM_TIMA
.pwm_advanced(pin_a, &mut rcc)
.prescaler(prescaler)
.period(period)
.finalize(&mut hr_control);
out1.enable_rst_event(&cr1); // Set low on compare match with cr1
out1.enable_set_event(&timer); // Set high at new period
cr1.set_duty(period / 2);

let (mut timer, mut capture, _capture_ch2) = timer.split_capture();
timer.start(&mut hr_control);
out1.enable();

capture.enable_interrupt(true, &mut hr_control);
capture.add_event(&eev_input6);

info!("Setup DMA");
let streams = dp.DMA1.split(&rcc);
let config = DmaConfig::default()
.transfer_complete_interrupt(false)
.circular_buffer(true)
.memory_increment(true);

let first_buffer = cortex_m::singleton!(: [u32; 16] = [0; 16]).unwrap();
let mut transfer = streams.0.into_circ_peripheral_to_memory_transfer(
capture.enable_dma(dma_ch),
&mut first_buffer[..],
config,
);

transfer.start(|_| ());

let mut old_duty = 0;
loop {
for duty in (u32::from(period) / 10)..(9 * u32::from(period) / 10) {
let mut data = [0; 2];
transfer.read_exact(&mut data);
let [t1, t2] = data.map(capture::dma_value_to_signed);
cr1.set_duty(duty as u16);
info!("Capture: t1: {}, t2: {}, duty: {}, ", t1, t2, old_duty);
old_duty = duty;
}
}
}
Loading
Loading