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

Hrtim #70

Closed
wants to merge 16 commits into from
Closed

Hrtim #70

wants to merge 16 commits into from

Conversation

usbalbin
Copy link
Contributor

@usbalbin usbalbin commented May 20, 2023

This depends on #68 (and thus includes its commits)
Solves: #69

This is still quite messy and is not yet verified on actual hardware - Done some tests and seems to work, will do more tests soon

HRTIM

(desctiption mostly copied from #69, example updated)
From what I understand(correct me if I am wrong) looking at the stm32g474 and stm32g484. We have 6 timers, each timer has two outputs which may be routed to pins. So far it looks just as any other pwm timer, however the waveform for each output is defined by up to 32 event sources. Some of those are the ouput's own timer's compare registers(4) and the period wrap around(1), other than that there are lots of other sources like a selection of other timers compare registers, master timer etc. Safe to say, there is not simply one single set_duty that controls the waveform. Then there are dead time and, faults etc.

With that said perhaps it would be wise to start small with some sort of MVP. What would you think about something like splitting this in to three main types:

  • HrTimer - this is where we control the period, and overall timer modes and settings
  • CompareRegister - I guess this could implement the PwmPin trait even if it might not necessarily be the "duty" that is controlled with set_duty in all cases
  • Output - This is what owns an output pin, may be used for setting what events to listen to in order to form the wave form.
    This is now can now be used as:
let dp = stm32::Peripherals::take().expect("cannot take peripherals");
let cp = stm32::CorePeripherals::take().expect("cannot take core");
// Set system frequency to 16MHz * 75/4/2 = 150MHz
// This would lead to HrTim running at 150MHz * 32 = 4.8GHz...
let mut rcc = dp.RCC.freeze(rcc::Config::pll().pll_cfg(rcc::PllConfig {
    mux: rcc::PLLSrc::HSI,
    n: rcc::PllNMul::MUL_75,
    m: rcc::PllMDiv::DIV_4,
    r: Some(rcc::PllRDiv::DIV_2),
    ..Default::default()
}));

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

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

let gpioa = dp.GPIOA.split(&mut rcc);
let pin_a: PA8<Alternate<AF13>> = gpioa.pa8.into_alternate();
let pin_b: PA9<Alternate<AF13>> = gpioa.pa9.into_alternate();

//        .               .               .               .
//        .  30%          .               .               .
//         ----           .               .----           .
//out1    |    |          .               |    |          .
//        |    |          .               |    |          .
// --------    ----------------------------    --------------------
//        .               .----           .               .----
//out2    .               |    |          .               |    |
//        .               |    |          .               |    |
// ------------------------    ----------------------------    ----
//        .               .               .               .
//        .               .               .               .
let (mut timer, (mut cr1, _cr2, _cr3, _cr4), (mut out1, mut out2)) = dp
    .HRTIM_TIMA
    .pwm_advanced((pin_a, pin_b), &mut rcc)
    .prescaler(prescaler)
    .period(0xFFFF)
    .push_pull_mode(true) // Set push pull mode, out1 and out2 are
    // alternated every period with one being
    // inactive and the other getting to output its wave form
    // as normal
    .finalize();

out1.enable_rst_event(EventSource::Cr1); // Set low on compare match with cr1
out2.enable_rst_event(EventSource::Cr1);

out1.enable_set_event(EventSource::Period); // Set high at new period
out2.enable_set_event(EventSource::Period);

out1.enable();
out2.enable();

loop {
    // Step frequency from 18kHz to about 180kHz
    for i in 1..10 {
        let new_period = u16::MAX / i;

        cr1.set_duty(new_period / 3);
        timer.set_period(new_period);

        delay.delay(500_u32.millis());
    }
}

TODO:

  • Verify that the described frequencies are correct in doc etc.
  • Wait for Use fugit #68
  • Implement half mode, maybe
  • Cleanup

src/pwm/hrtim.rs Outdated
Comment on lines 616 to 620
// TODO: Somehow, there is no rstf1r
//HRTIM_TIMF: HrOut1: tf1oen, setf1r, rstf1r,

// TODO: Somehow, there is no tf2oen
//HRTIM_TIMF: HrOut2: tf2oen, setf2r, rstf2r,
Copy link
Contributor Author

@usbalbin usbalbin May 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit weird, the reference says there should be a tf2oen... Is this a bug in the crate stm32g4? I believe the HRTIM_TIMF timer might be unique to stm32g474/stm32g484 thus should be missing in stm32f334 and stm32h7.

@usbalbin
Copy link
Contributor Author

Any thoughts? :)

Does the interface make sense? Do you have any suggestions? :)

usbalbin added 5 commits June 7, 2023 15:51
* Rcc enable is now handled for the entire HRTIM peripheral by dp.HRTIM_COMMON.hr_control() instead of by every timer
* HRTIM calibration is now mandatory, also handled by `dp.HRTIM_COMMON.hr_control()` but also by running on that result `_.wait_for_calibration().
* Add `get_state` for `HrOutput` to check what state an output is in: `Idle`, `Running` or `Fault`
@no111u3
Copy link
Collaborator

no111u3 commented Nov 28, 2023

@usbalbin does this PR is active?

@usbalbin
Copy link
Contributor Author

I have made a lot more changes in another branch. However that branch also has a lot of unrelated changes so I will at some point try to clean that up and make a new PR. Or more likely a set of new PRs since there is quite a lot hrtim stuff.

@usbalbin does this PR is active?

So, no.

@usbalbin usbalbin closed this Nov 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants