-
Notifications
You must be signed in to change notification settings - Fork 32
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
Add Peripherals::steal behind rtic
feature. Add rtic-led.rs
, rtic-blink.rs
and rtic-uart-log.rs
examples.
#64
Conversation
966fc7d
to
528dc44
Compare
As proposed by Mitch in #64. As of this commit, the Teensy CLI loader does not reject the *.hex file. See the previous commit for details.
528dc44
to
1981e22
Compare
This adds two new changes for the `rtic` feature: 1. Re-export the `Interrupt` and `NVIC_PRIO_BITS` as `rtic` requires these for generated code related to interrupts. 2. Remove the `SysTick` definition to remove duplicating the `rtic` definition.
As of imxrt-rs/imxrt-hal#67 and imxrt-rs/imxrt-hal#68 the `ral` workaround is no longer necessary. As of imxrt-rs/imxrt-hal#69 `Peripherals::steal` is available on the master branch.
1981e22
to
aa896f1
Compare
I'm currently having a go at implementing a Here's my WIP based on following along with the rtic book example: //! An adaptation of the `rtic_led.rs` example that demonstrates:
//!
//! 1. how to share late resources and
//! 2. how to use the systick interrupt to cause the LED to blink.
//!
//! NOTE: This example requires the `rtic` feature to be enabled.
#![no_std]
#![no_main]
use embedded_hal::digital::v2::{OutputPin, ToggleableOutputPin};
use panic_halt as _;
use rtic::cyccnt::U32Ext;
use teensy4_bsp as bsp;
// The CYCCNT counts in clock cycles - using the clock hz should give us a ~1 second period?
const PERIOD: u32 = bsp::hal::ccm::PLL1::ARM_HZ;
#[rtic::app(device = teensy4_bsp, monotonic = rtic::cyccnt::CYCCNT, peripherals = true)]
const APP: () = {
struct Resources {
led: bsp::LED,
}
#[init(schedule = [blink])]
fn init(mut cx: init::Context) -> init::LateResources {
// Initialise the monotonic timer.
cx.core.DCB.enable_trace();
cx.core.DWT.enable_cycle_counter();
// Schedule the first blink.
cx.schedule.blink(cx.start + PERIOD.cycles()).unwrap();
let mut led = bsp::configure_led(&mut cx.device.gpr, cx.device.pins.p13);
led.set_high().unwrap();
init::LateResources { led }
}
#[task(resources = [led], schedule = [blink])]
fn blink(cx: blink::Context) {
cx.resources.led.toggle().unwrap();
// Schedule the following blink.
cx.schedule.blink(cx.scheduled + PERIOD.cycles()).unwrap();
}
// RTIC requires that unused interrupts are declared in an extern block when
// using software tasks; these free interrupts will be used to dispatch the
// software tasks.
extern "C" {
fn LPUART8();
}
}; Currently the teensy seems to immediately halt (a few ms) after setting the LED high within Anyway I'm finishing up for the night, but just thought I'd share progress in case you have any advice in the meantime. |
What does that look like? Does it look as if the LED turns on, it turns off, and the bootloader LED turns on? If so, I've seen that in other contexts. It seems to happen when we start from reprogram, and we quickly hit WFI. In fact, the simple for _ in 0..10_000_000 {
core::sync::atomic::spin_loop_hint();
} just before returning the late resources. I haven't figured this out yet, but it's definitely in the startup code... Once I workaround that, I can show that the example has a steady, always-on LED. One thing that might be worth checking is how RTIC configures SYSTICK. SYSTICK can use one of two clock sources: the core, and an 'external' source. I've never tried using the core source. If we simply change The BSP doesn't set the ARM clock by default, so don't forget to set the ARM clock if we're expecting Lines 28 to 32 in 2114788
|
A slightly more advanced adaptation of the `rtic_led.rs` example that demonstrates: 1. how to share late resources and 2. how to use the systick interrupt to cause the LED to blink.
Exactly this. After applying your After this I spent a while trying to work out why
I had omitted the #[idle]
fn idle(_cx: idle::Context) -> ! {
loop {
core::sync::atomic::spin_loop_hint();
}
} And sure enough the teensy started blinking! The rate appears very close to my guesstimate of one second per I have added a commit with the new working On a slightly related note, this PR looks very interesting w.r.t. to making timers a little more human-friendly in a device-agnostic manner - could be well worth keeping an eye on rather than trying to solve the problem a second time downstream. |
See the comment in the `init()` method. This lets us remove the busy-loop in idle, while still blinking at 1000ms.
Awesome work proving-out the scheduler! I measured the blinking interval with my logic analyzer: 1.00000454 seconds. And good find regarding teensy4-rs/examples/rtic_blink.rs Lines 31 to 41 in 3e260b8
Check out 3e260b8 for more information. If we'd like this approach to represent the
The standard Teensy startup code does have a delay. Not sure if it's to guard against what we're observing, or for another reason. |
Thanks for the explanation about CCM mode! I've added your commit to the PR 👍 |
OK, next on my list is an To begin, I'm aiming to get something simple working like this: #![no_std]
#![no_main]
use embedded_hal::digital::v2::ToggleableOutputPin;
use panic_halt as _;
use teensy4_bsp as bsp;
#[rtic::app(device = teensy4_bsp, peripherals = true)]
const APP: () = {
struct Resources {
led: bsp::LED,
}
#[init]
fn init(mut cx: init::Context) -> init::LateResources {
init_delay();
let led = bsp::configure_led(&mut cx.device.gpr, cx.device.pins.p13);
init::LateResources { led }
}
#[task(binds = USB_OTG1, resources = [led])]
fn usb(cx: usb::Context) {
cx.resources.led.toggle().unwrap();
}
#[idle]
fn idle(_cx: idle::Context) -> ! {
loop {
core::sync::atomic::spin_loop_hint();
}
}
};
fn init_delay() {
for _ in 0..10_000_000 {
core::sync::atomic::spin_loop_hint();
}
} I'm hoping to cause the LED to toggle by triggering the As expected this doesn't work just yet. Not only does I noticed that I then tried adding the following to let usb_rx = cx.device.usb.init(bsp::usb::LoggingConfig {
filters: &[("usb", None)],
..Default::default()
}); While this seems to compile successfully (with the added |
Fully integrating the USB stack with RTIC might be tricky. There are some brief considerations documented here, in the
If the goal is a simple debugging interface, I'll also note that we have a serial logger. If you have a USB to serial cable (like this), you can have the same logging experience with the |
Oh great! I have one of these lying around, I might see if I can get debugging via UART working first then. If I can I imagine it might come in handy when hacking on the USB stack. |
fffd895
to
5b76bba
Compare
The example is an adaption of `rtic-blink.rs` that logs via the teensy 4.0 LPUART2 interface on each blink. The example also demonstrates the LPUART2 interrupt and enqueues the received bytes so that they may be logged on the next blink.
5b76bba
to
5b82a6f
Compare
rtic
feature. Add examples/rtic_led.rs.rtic
feature. Add rtic-led.rs
, rtic-blink.rs
and rtic-uart-log.rs
examples.
OK, UART logging example added with a working interrupt! |
Thanks again for putting all of this together! Is there anything else you'd like to add? All LGTM; I'm happy to merge it. |
Likewise, I'm happy for this to land as is! I'd like to try and get an Thanks for your timely responses and guidance on all this! |
91: De-couple SysTick and USB; support USB and RTIC r=mciantyre a=mciantyre The PR separates the USB and SysTick drivers, so we can use USB CDC logging and I/O without running SysTick. Before this PR, the USB driver depended on SysTick for timing a polling loop. With this PR, the USB driver no longer depends on SysTick, and we can use these BSP features independently. The PR addresses the limitations noted in #66 and #64. Now that we can use USB without SysTick, **we can use the USB module with RTIC**. The PR adds two RTIC examples that use USB for logging and direct CDC I/O. The PR includes breaking changes throughout the USB interface. These changes should support BSP power-users who want to understand USB read / write events. The changes also make USB peripheral ownership explicit in user programs, and reduce the responsibility of the BSP. See the CHANGELOG for the specific breakages and migration tips. This PR supersedes #66. Co-authored-by: mitchmindtree <mitchell.nordine@gmail.com> Co-authored-by: Ian McIntyre <ianpmcintyre@gmail.com>
This PR is based on #63 and in turn the diff includes those changes.
Closes #62