what is the proper way to configure and use the gpt2 peripheral?
mutantbob opened this issue · 3 comments
I am using gpt1 to blink an LED. I want to use gpt2 to toggle the virtual shift modifier on my USB keyboard experiment. I have the following code (derived from https://github.com/imxrt-rs/imxrt-usbd/blob/master/examples/teensy4/src/support.rs)
pub fn rig_timer<'a>(
duration: Duration,
dcdc: &mut DCDC,
gpt1: Unclocked,
ccm_pll1: &mut imxrt_hal::ccm::PLL1,
ccm_handle: &'a mut imxrt_hal::ccm::Handle,
ccm_perclk: imxrt_hal::ccm::perclk::Multiplexer,
) -> (GPT, imxrt_hal::ccm::perclk::Configured<'a>) {
let (_frequency, ipg_hz) = ccm_pll1.set_arm_clock(hal::ccm::PLL1::ARM_HZ, ccm_handle, dcdc);
let mut cfg = ccm_perclk.configure(
ccm_handle,
hal::ccm::perclk::PODF::DIVIDE_3,
hal::ccm::perclk::CLKSEL::IPG(ipg_hz),
);
let gpt1 = rig_timer_2(duration, gpt1, &mut cfg);
(gpt1, cfg)
}
pub fn rig_timer_2(duration: Duration, gpt: Unclocked, cfg: &mut Configured<'_>) -> GPT {
let mut gpt = gpt.clock(cfg);
gpt.set_wait_mode_enable(true);
gpt.set_mode(hal::gpt::Mode::Reset);
let gpt_ocr: hal::gpt::OutputCompareRegister = hal::gpt::OutputCompareRegister::One;
gpt.set_output_compare_duration(gpt_ocr, duration);
gpt
}
and I use it later
let (gpt1, mut clock_config) = support::rig_timer(
duration,
&mut dcdc,
gpt1,
&mut ccm.pll1,
&mut ccm.handle,
ccm.perclk,
);
let gpt2 = support::rig_timer_2(
core::time::Duration::from_millis(200),
gpt2,
&mut clock_config,
);
but it appears that only gpt1 is usable with the idiom (also from support.rs)
pub fn time_elapse(gpt: &mut hal::gpt::GPT, func: impl FnOnce()) {
let mut status = gpt.output_compare_status(GPT_OCR);
if status.is_set() {
status.clear();
func();
}
}
If I use gpt2, I never observe status.is_set()
being true.
I flipped things so that gpt2 controls the LED and gpt1 controls the virtual shift key, and then the shift key flips like I want, but the LED never toggles, so I am reasonably confident the problem is with gpt2 (probably my configuration of gpt2).
What am I overlooking? What should I change to make gpt2 work the way I think it should?
Sorry for the trouble. Nothing seems wrong with your routines. The one thing I don't explicitly see in these snippets is calls to set_enable(true)
. That call must be happening for GPT1, or it wouldn't work. Is a similar call also happening for GPT2?
As a small sanity check, I
- took all the imxrt-usbd examples, and changed them to work with GPT2. Everything looks OK. But, that doesn't test two GPTs being used at the same time...
- hacked a teensy4-bsp example to use both timers for timing events. Looks OK there, too.
Your initial instinct was correct. I was missing gpt2.set_enable(true)
.
I wonder if this means that there should be separate types for the object before and after set_enable
. If there are multiple methods that only make sense to call after set_enable, this might be worth investigating (although the API change would be inconvenient to all downstream projects).
This is precisely the use case for a type state, but at some point the type states become burdensome to manage. It's a tradeoff as always.