Skip to content

Commit

Permalink
examples: Updates all Tier 1 BSP examples to use RTIC v2 and the RTC …
Browse files Browse the repository at this point in the history
…monotonic where applicable

* Ensures that all Tier 1 BSPs have all examples listed in Cargo.toml in alphabetical order.
* Tier 1 BSP changes:
  * samd11_bare
    * Adds the `blinky_rtic` example.
  * metro_m0
    * Updates the `blinky_rtic` example to use RTIC v2 and the RTC monotonic.
  * feather_m0
    * Updates the `blinky_rtic` example to use the RTC monotonic.
    * Renames the `blinky_monotonic` example to `blinky_embassy`, which is more apt since they both use a monotonic.
    * Updates the `blinky_embassy` example to use the RTC monotonic as well, showing that this can be done despite it being a monotonic written for RTIC.
  * pygamer
    * Adds the `blinky_rtic` example.
  * metro_m4
    * Adds the `blinky_rtic` example.
  * feather_m4
    * Adds the `blinky_rtic` example.
    * Updates the `clocking_v2` example to use RTIC v2.
  * atsame54_xpro
    * Updates the `blinky_rtic` example to use RTIC v2 and the RTC monotonic.
    * Updates the `mcan` example to use RTIC v2 and the RTC monotonic.
  • Loading branch information
kyp44 committed Jan 30, 2025
1 parent c80f306 commit 507a6e4
Show file tree
Hide file tree
Showing 23 changed files with 796 additions and 356 deletions.
36 changes: 19 additions & 17 deletions boards/atsame54_xpro/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,58 +1,60 @@
[package]
name = "atsame54_xpro"
version = "0.11.0"
authors = [
"Karsten Große <[email protected]>",
"John Little <[email protected]>"
"Karsten Große <[email protected]>",
"John Little <[email protected]>",
]
categories = ["embedded", "hardware-support", "no-std"]
description = "Board Support crate for the SAM E54 Xplained Pro Evaluation Kit"
edition = "2021"
keywords = ["no-std", "arm", "cortex-m", "embedded-hal"]
categories = ["embedded", "hardware-support", "no-std"]
license = "MIT OR Apache-2.0"
edition = "2021"
repository = "https://github.com/atsamd-rs/atsamd"
name = "atsame54_xpro"
readme = "README.md"
repository = "https://github.com/atsamd-rs/atsamd"
version = "0.11.0"

[dependencies.cortex-m-rt]
version = "0.7"
optional = true
version = "0.7"

[dependencies.cortex-m]
version = "0.7"
features = ["critical-section-single-core"]
version = "0.7"

[dependencies.atsamd-hal]
default-features = false
path = "../../hal"
version = "0.21.0"
default-features = false

[dependencies.usb-device]
version = "0.3.1"
optional = true
version = "0.3.1"

[dev-dependencies]
mcan = "0.2"
cortex-m-rtic = "1.1"
dwt-systick-monotonic = "1.1"
panic-rtt-target = { version = "0.1", features = ["cortex-m"] }
rtt-target = { version = "0.3", features = ["cortex-m"] }
panic-rtt-target = {version = "0.1", features = ["cortex-m"]}
rtic = {version = "2.1.2", features = ["thumbv7-backend"]}
rtt-target = {version = "0.3", features = ["cortex-m"]}

[features]
default = ["rt", "atsamd-hal/same54p"]
dma = ["atsamd-hal/dma"]
max-channels = ["dma", "atsamd-hal/max-channels"]
# Enable async support from atsamd-hal
async = ["atsamd-hal/async"]
can = ["atsamd-hal/can"]
rt = ["cortex-m-rt", "atsamd-hal/same54p-rt"]
usb = ["atsamd-hal/usb", "usb-device"]
can = ["atsamd-hal/can"]
# Enable rtic support from atsamd-hal
rtic = ["atsamd-hal/rtic"]

[[example]]
name = "blinky_basic"

[[example]]
name = "blinky_rtic"
required-features = ["rtic"]

[[example]]
name = "mcan"
required-features = ["can"]
required-features = ["can", "rtic"]
81 changes: 42 additions & 39 deletions boards/atsame54_xpro/examples/blinky_rtic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,20 @@

use atsame54_xpro as bsp;
use bsp::hal;
use bsp::hal::clock::v2 as clock;
use dwt_systick_monotonic::DwtSystick;
use dwt_systick_monotonic::{fugit::RateExtU32, ExtU32};
// TODO: Any reason this cannot be in a HAL's prelude?
use hal::ehal::digital::StatefulOutputPin;
use hal::clock::v2::{clock_system_at_reset, osculp32k::OscUlp1k, rtcosc::RtcOsc};
use hal::prelude::*;
use hal::rtc::rtic::rtc_clock;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
// TODO: Any reason this cannot be in a HAL's prelude?
use hal::ehal::digital::StatefulOutputPin;

hal::rtc_monotonic!(Mono, rtc_clock::Clock1k);

#[rtic::app(device = hal::pac, peripherals = true, dispatchers = [FREQM])]
#[rtic::app(device = hal::pac, dispatchers = [FREQM])]
mod app {
use super::*;

#[monotonic(binds = SysTick, default = true)]
type Mono = DwtSystick<12_000_000>;

#[shared]
struct Shared {}

Expand All @@ -27,46 +26,50 @@ mod app {
}

#[init]
fn init(mut ctx: init::Context) -> (Shared, Local, init::Monotonics) {
fn init(ctx: init::Context) -> (Shared, Local) {
let mut device = ctx.device;
let mut core: rtic::export::Peripherals = ctx.core;

rtt_init_print!();

let (_buses, clocks, tokens) = clock::clock_system_at_reset(
ctx.device.oscctrl,
ctx.device.osc32kctrl,
ctx.device.gclk,
ctx.device.mclk,
&mut ctx.device.nvmctrl,
let (_buses, clocks, tokens) = clock_system_at_reset(
device.oscctrl,
device.osc32kctrl,
device.gclk,
device.mclk,
&mut device.nvmctrl,
);

let pins = bsp::Pins::new(ctx.device.port);
let xosc = clock::xosc::Xosc::from_crystal(
tokens.xosc1,
bsp::pin_alias!(pins.xosc1_x_in),
bsp::pin_alias!(pins.xosc1_x_out),
// Xosc1 on Same54Xpro is 12 MHz
12_u32.MHz(),
)
.enable();
// Enable the 1 kHz clock from the internal 32 kHz source
let (osculp1k, _) = OscUlp1k::enable(tokens.osculp32k.osculp1k, clocks.osculp32k_base);

let (gclk0, _, _) = clocks.gclk0.swap_sources(clocks.dfll, xosc);
// Enable the RTC clock with the 1 kHz source.
// Note that currently the proof of this (the `RtcOsc` instance) is not
// required to start the monotonic.
let _ = RtcOsc::enable(tokens.rtcosc, osculp1k);

let mono = DwtSystick::new(
&mut ctx.core.DCB,
ctx.core.DWT,
ctx.core.SYST,
gclk0.freq().to_Hz(),
);
// Start the monotonic
Mono::start(device.rtc);

let led = bsp::pin_alias!(pins.led).into();
let pins = bsp::Pins::new(device.port);

led::spawn().unwrap();
// We can use the RTC in standby for maximum power savings
core.SCB.set_sleepdeep();

(Shared {}, Local { led }, init::Monotonics(mono))
blink_led::spawn().unwrap();

(
Shared {},
Local {
led: bsp::pin_alias!(pins.led).into(),
},
)
}

#[task(local = [led])]
fn led(ctx: led::Context) {
ctx.local.led.toggle().unwrap();
/// This function is spawned and never returns.
#[task(priority = 1, local=[led])]
async fn blink_led(ctx: blink_led::Context) {
StatefulOutputPin::toggle(ctx.local.led).unwrap();
rprintln!(
"LED {}!",
if ctx.local.led.is_set_high().unwrap() {
Expand All @@ -75,6 +78,6 @@ mod app {
"ON"
}
);
led::spawn_at(monotonics::now() + 200.millis()).unwrap();
Mono::delay(200u64.millis()).await;
}
}
69 changes: 36 additions & 33 deletions boards/atsame54_xpro/examples/mcan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@

use atsame54_xpro as bsp;
use bsp::hal;
use clock::{osculp32k::OscUlp1k, rtcosc::RtcOsc};
use hal::clock::v2 as clock;
use hal::eic::{Ch15, Eic, ExtInt, Sense};
use hal::gpio::{Interrupt as GpioInterrupt, *};
use hal::prelude::*;

use dwt_systick_monotonic::{DwtSystick, ExtU32};
use hal::rtc::rtic::rtc_clock;

use mcan::embedded_can as ecan;
use mcan::generic_array::typenum::consts::*;
Expand All @@ -45,6 +45,8 @@ use mcan::{
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};

hal::rtc_monotonic!(Mono, rtc_clock::Clock1k);

pub struct Capacities;

impl mcan::messageram::Capacities for Capacities {
Expand Down Expand Up @@ -89,13 +91,10 @@ type Aux = mcan::bus::Aux<
>;
type Button = ExtInt<Pin<PB31, GpioInterrupt<PullUp>>, Ch15>;

#[rtic::app(device = hal::pac, peripherals = true, dispatchers = [FREQM])]
#[rtic::app(device = hal::pac, dispatchers = [FREQM])]
mod app {
use super::*;

#[monotonic(binds = SysTick, default = true)]
type Mono = DwtSystick<48_000_000>;

#[shared]
struct Shared {}

Expand All @@ -115,32 +114,40 @@ mod app {
#[link_section = ".can"]
can_memory: SharedMemory<Capacities> = SharedMemory::new()
])]
fn init(mut ctx: init::Context) -> (Shared, Local, init::Monotonics) {
fn init(ctx: init::Context) -> (Shared, Local) {
let mut device = ctx.device;

rtt_init_print!();
rprintln!("Application up!");

let (_buses, clocks, tokens) = clock::clock_system_at_reset(
ctx.device.oscctrl,
ctx.device.osc32kctrl,
ctx.device.gclk,
ctx.device.mclk,
&mut ctx.device.nvmctrl,
device.oscctrl,
device.osc32kctrl,
device.gclk,
device.mclk,
&mut device.nvmctrl,
);

let (_, _, _, mut mclk) = unsafe { clocks.pac.steal() };
// Enable the 1 kHz clock from the internal 32 kHz source
let (osculp1k, _) = OscUlp1k::enable(tokens.osculp32k.osculp1k, clocks.osculp32k_base);

let mono = DwtSystick::new(
&mut ctx.core.DCB,
ctx.core.DWT,
ctx.core.SYST,
clocks.gclk0.freq().to_Hz(),
);
// Enable the RTC clock with the 1 kHz source.
// Note that currently the proof of this (the `RtcOsc` instance) is not
// required to start the monotonic.
let _ = RtcOsc::enable(tokens.rtcosc, osculp1k);

let pins = bsp::Pins::new(ctx.device.port);
// Start the monotonic
Mono::start(device.rtc);

// Need to get the MCLK peripheral back due to things in the HAL still using v1
// of the clocks API
let (_, _, _, mut mclk) = unsafe { clocks.pac.steal() };

let pins = bsp::Pins::new(device.port);

let (pclk_eic, gclk0) = clock::pclk::Pclk::enable(tokens.pclks.eic, clocks.gclk0);

let eic_channels = Eic::new(&mut mclk, pclk_eic.into(), ctx.device.eic).split();
let eic_channels = Eic::new(&mut mclk, pclk_eic.into(), device.eic).split();
let mut button = bsp::pin_alias!(pins.button).into_pull_up_ei(eic_channels.15);
button.sense(Sense::Fall);
button.debounce();
Expand All @@ -160,7 +167,7 @@ mod app {
clocks.ahbs.can1,
can1_rx,
can1_tx,
ctx.device.can1,
device.can1,
);

let mut can =
Expand Down Expand Up @@ -217,7 +224,7 @@ mod app {

let led = bsp::pin_alias!(pins.led).into();

bump_activity_led();
let _ = activity_led::spawn(true);

(
Shared {},
Expand All @@ -231,14 +238,13 @@ mod app {
tx_event_fifo,
aux,
},
init::Monotonics(mono),
)
}

#[task(binds = EIC_EXTINT_15, local = [counter: u16 = 0, button, tx_event_fifo, aux, tx])]
fn button(ctx: button::Context) {
ctx.local.button.clear_interrupt();
bump_activity_led();
let _ = activity_led::spawn(true);
rprintln!("Button pressed! Status:");
while let Some(e) = ctx.local.tx_event_fifo.pop() {
rprintln!("TxEvent: {:0X?}", e);
Expand Down Expand Up @@ -273,7 +279,7 @@ mod app {

#[task(priority = 2, binds = CAN1, local = [line_interrupts, rx_fifo_0, rx_fifo_1])]
fn can1(mut ctx: can1::Context) {
bump_activity_led();
let _ = activity_led::spawn(true);
let line_interrupts = ctx.local.line_interrupts;
for interrupt in line_interrupts.iter_flagged() {
match interrupt {
Expand All @@ -292,18 +298,15 @@ mod app {
}
}

#[task(local = [led])]
fn activity_led(ctx: activity_led::Context, led_on: bool) {
/// This function is spawned and never returns.
#[task(priority = 1, local = [led])]
async fn activity_led(ctx: activity_led::Context, led_on: bool) {
let _ = ctx.local.led.set_state((!led_on).into());
if led_on {
let _ = activity_led::spawn_after(100.millis(), false);
Mono::delay(100u64.millis()).await;
}
}

fn bump_activity_led() {
let _ = activity_led::spawn(true);
}

fn log(fifo: &str, message: &impl mcan::message::Raw) {
rprintln!("New message received ({})", fifo);
rprintln!("id: {:0X?}", message.id());
Expand Down
Loading

0 comments on commit 507a6e4

Please sign in to comment.