-
Notifications
You must be signed in to change notification settings - Fork 51
Description
Would there be any interest in support for the HRTIM peripheral? The peripheral is useful for things like generating PWM waveforms for powersupplies and similar. It is available in the stm32g474 and stm32g484, and some processors from stm32f3xx and stm32h7xx. I have not found a rust implementation for it yet, so as far as I know this would probably be the first?
If this is something that would be accepted as a PR, do you have any suggestions for how to think when creating an API for it?
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 settingsCompareRegister
- I guess this could implement the PwmPin trait even if it might not necessarily be the "duty" that is controlled withset_duty
in all casesOutput
- This is what owns an output pin, may be used for setting what events to listen to in order to form the wave form.
I would imagine something roughly like this
// . .
// . 30% .
// ---- . ----
//out1 | | . | |
// | | . | |
// -------- ---------------------------- --------------------
// . ---- . ----
//out2 . | | | |
// . | | | |
// ------------------------ ---------------------------- ----
type Prescaler = Pscl4; // Prescaler of 4
let (timer, cr1, _cr2, _cr3, _cr4, (out1, out2)) = dp.HRTIM_TIMA.pwm_hrtim::<Prescaler>((pin_a, pin_b), rcc)
.period(0xFFFF)
.mode(Mode::PushPull) // 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.rst_event(EventSource::Cr1); // Set low on compare match with cr1
out2.rst_event(EventSource::Cr1);
out1.set_event(EventSource::Period); // Set high at new period
out2.set_event(EventSource::Period);
// ^
// |
// *---- Perhaps multiple EventSources could be Or:ed together?
cr1.set_duty(timer.get_period() / 3);
timer.set_period(foo);