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

Async API #635

Merged
merged 4 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build-bsp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ jobs:

- name: Install Rust
run: |
rustup update
rustup set profile minimal
rustup override set ${{ matrix.toolchain }}
target=$(cat ./crates.json | jq -Mr --arg board '${{ matrix.bsp.name }}' -c '.boards | .[$board] | .target')
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/build-hal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ jobs:

- name: Install Rust
run: |
rustup update
rustup set profile minimal
rustup override set ${{ matrix.toolchain }}
target=$(cat ./crates.json | jq -Mr --arg pac "${{matrix.pac}}" -c '.hal_build_variants["${{matrix.pac}}"].target')
Expand Down
15 changes: 15 additions & 0 deletions .release-plz.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,18 @@ release_always = false

[changelog]
protect_breaking_commits = true

commit_parsers = [
{ message = "^feat", group = "added" },
{ message = "^changed", group = "changed" },
{ message = "^deprecated", group = "deprecated" },
{ message = "^fix", group = "fixed" },
{ message = "^security", group = "security" },
{ message = "^deps", group = "dependencies" },
{ message = "^removed", group = "removed" },
{ message = "^docs", group = "documentation" },
{ message = "^refactor", group = "refactored" },
{ message = "^style", group = "formatted" },
{ message = "^examples", group = "examples"},
{ message = "^.*", group = "other" },
]
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,25 @@ The Peripheral Access Crates (PACs) are automatically generated from Microchip S
[wio_terminal]: https://github.com/atsamd-rs/atsamd/tree/master/boards/wio_terminal
[xiao_m0]: https://github.com/atsamd-rs/atsamd/tree/master/boards/xiao_m0


### `async` APIs

[`atsamd_hal`](https://crates.io/crate/atsamd-hal) provides APIs for using `async`/`await` constructs with some of its peripherals. To enable `async` support, use the `async` Cargo feature.
Detailed documentation is provided in the `atsamd_hal::async_hal` module. The [metro_m4](https://github.com/atsamd-rs/atsamd/tree/master/boards/metro_m4/examples) and
[feather_m0](https://github.com/atsamd-rs/atsamd/tree/master/boards/feather_m0/examples) feature complete examples showing how to use async APIs.

Please note that you must bring your own executor runtime such as [`embassy-executor`](https://crates.io/crates/embassy-executor) or [`rtic`](https://crates.io/crates/rtic) to be able to
use the async APIs.

#### Supported peripherals

* SPI
* I2C
* USART
* DMAC
* EIC (GPIO interrupts)
* Timers

### Examples

The BSPs include examples to quickly get up and running with the board. Building the examples
Expand Down
3 changes: 3 additions & 0 deletions atsamd-hal-macros/devices.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ families:
samd11c: ["pins-14", "pa28"]
samd11d: ["pins-24", "pa27", "pa28"]
peripherals:
- nvic
- serial-numbers
- dsu
- clock
Expand Down Expand Up @@ -48,6 +49,7 @@ families:
samd21el: ["pins-32l"]
samd21gl: ["pins-48l", "pa28"]
peripherals:
- nvic
- serial-numbers
- dsu
- clock
Expand Down Expand Up @@ -89,6 +91,7 @@ families:
same54n: ["pins-100"]
same54p: ["pins-128"]
peripherals:
- nvic
- serial-numbers
- cmcc
- dsu
Expand Down
3 changes: 3 additions & 0 deletions boards/atsame54_xpro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ 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"]
rt = ["cortex-m-rt", "atsamd-hal/same54p-rt"]
usb = ["atsamd-hal/usb", "usb-device"]
can = ["atsamd-hal/can"]
Expand Down
12 changes: 6 additions & 6 deletions boards/atsame54_xpro/examples/mcan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,12 @@ mod app {

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

let mut eic = hal::eic::init_with_ulp32k(&mut mclk, pclk_eic.into(), ctx.device.eic);
let mut button = bsp::pin_alias!(pins.button).into_pull_up_ei();
eic.button_debounce_pins(&[button.id()]);
button.sense(&mut eic, Sense::Fall);
button.enable_interrupt(&mut eic);
eic.finalize();
let mut eic =
hal::eic::init_with_ulp32k(&mut mclk, pclk_eic.into(), ctx.device.eic).finalize();
let mut button = bsp::pin_alias!(pins.button).into_pull_up_ei(&mut eic);
button.sense(Sense::Fall);
button.debounce();
button.enable_interrupt();

let can1_rx = bsp::pin_alias!(pins.ata6561_rx).into_mode();
let can1_tx = bsp::pin_alias!(pins.ata6561_tx).into_mode();
Expand Down
1 change: 1 addition & 0 deletions boards/feather_m0/.cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ rustflags = [
# See https://github.com/rust-embedded/cortex-m-quickstart/pull/95
"-C", "link-arg=--nmagic",
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-Tdefmt.x" # uncomment if using defmt
]

[target.thumbv6m-none-eabi]
Expand Down
45 changes: 40 additions & 5 deletions boards/feather_m0/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,23 @@ version = "0.3"
optional = true

[dev-dependencies]
cortex-m-rtic = "1.0"
embassy-executor = { version = "0.6.2", features = ["arch-cortex-m", "executor-thread", "task-arena-size-64"] }
rtic = { version = "2.1.1", features = ["thumbv6-backend"] }
rtic-monotonics = { version = "1.3.0", features = ["cortex-m-systick", "systick-10khz"] }
fugit = "0.3.6"
cortex-m = "0.7"
usbd-serial = "0.2"
cortex-m-semihosting = "0.3"
ssd1306 = "0.7"
embedded-graphics = "0.7.1"
drogue-nom-utils = "0.1"
nom = { version = "5", default-features = false }
heapless = "0.7"
heapless = "0.8"
panic-halt = "0.2"
panic-semihosting = "0.5"
panic-semihosting = "0.6"
defmt = "0.3"
defmt-rtt = "0.4"
panic-probe = "0.3"

[features]
# ask the HAL to enable atsamd21g support
Expand All @@ -61,6 +67,8 @@ rfm = []
express = []
dma = ["atsamd-hal/dma"]
max-channels = ["dma", "atsamd-hal/max-channels"]
# Enable async support from atsamd-hal
async = ["atsamd-hal/async"]
# Enable pins for the adalogger SD card reader
adalogger = []
# Enable pins for Feather with WINC1500 wifi
Expand All @@ -72,6 +80,10 @@ use_semihosting = []
[[example]]
name = "blinky_basic"

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

[[example]]
name = "timers"

Expand Down Expand Up @@ -122,8 +134,7 @@ name = "adalogger"
required-features = ["adalogger", "usb", "sdmmc"]

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

[[example]]
name = "uart"
Expand All @@ -143,3 +154,27 @@ required-features = ["dma"]
[[example]]
name = "spi"
required-features = ["dma"]

[[example]]
name = "async_dmac"
required-features = ["dma", "async"]

[[example]]
name = "async_timer"
required-features = ["async"]

[[example]]
name = "async_eic"
required-features = ["async"]

[[example]]
name = "async_i2c"
required-features = ["dma", "async"]

[[example]]
name = "async_spi"
required-features = ["dma", "async"]

[[example]]
name = "async_uart"
required-features = ["dma", "async"]
73 changes: 73 additions & 0 deletions boards/feather_m0/examples/async_dmac.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//! This example shows a safe API to
//! execute a memory-to-memory DMA transfer

#![no_std]
#![no_main]

use defmt_rtt as _;
use panic_probe as _;

atsamd_hal::bind_interrupts!(struct Irqs {
DMAC => atsamd_hal::dmac::InterruptHandler;
});

use bsp::hal;
use bsp::pac;
use feather_m0 as bsp;
use hal::{
clock::GenericClockController,
dmac::{DmaController, PriorityLevel, TriggerAction, TriggerSource},
};

#[embassy_executor::main]
async fn main(_s: embassy_executor::Spawner) {
let mut peripherals = pac::Peripherals::take().unwrap();
let _core = pac::CorePeripherals::take().unwrap();

let _clocks = GenericClockController::with_external_32kosc(
peripherals.gclk,
&mut peripherals.pm,
&mut peripherals.sysctrl,
&mut peripherals.nvmctrl,
);

// Initialize DMA Controller
let dmac = DmaController::init(peripherals.dmac, &mut peripherals.pm);

// Turn dmac into an async controller
let mut dmac = dmac.into_future(crate::Irqs);
// Get individual handles to DMA channels
let channels = dmac.split();

// Initialize DMA Channel 0
let mut channel = channels.0.init(PriorityLevel::Lvl0);

let mut source = [0xff; 100];
let mut dest = [0x0; 100];

defmt::info!(
"Launching a DMA transfer.\n\tSource: {:#x}\n\tDestination: {:#x}",
&source,
&dest
);

channel
.transfer_future(
&mut source,
&mut dest,
TriggerSource::Disable,
TriggerAction::Block,
)
.await
.unwrap();

defmt::info!(
"Finished DMA transfer.\n\tSource: {:#x}\n\tDestination: {:#x}",
&source,
&dest
);

loop {
cortex_m::asm::wfi();
sajattack marked this conversation as resolved.
Show resolved Hide resolved
}
}
60 changes: 60 additions & 0 deletions boards/feather_m0/examples/async_eic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#![no_std]
#![no_main]

use defmt_rtt as _;
use panic_probe as _;

use bsp::pac;
use bsp::{hal, pin_alias};
use feather_m0 as bsp;
use hal::{
clock::{enable_internal_32kosc, ClockGenId, ClockSource, GenericClockController},
ehal::digital::StatefulOutputPin,
eic::{
pin::{ExtInt2, Sense},
EIC,
},
gpio::{Pin, PullUpInterrupt},
};

atsamd_hal::bind_interrupts!(struct Irqs {
EIC => atsamd_hal::eic::InterruptHandler;
});

#[embassy_executor::main]
async fn main(_s: embassy_executor::Spawner) {
let mut peripherals = pac::Peripherals::take().unwrap();
let _core = pac::CorePeripherals::take().unwrap();

let mut clocks = GenericClockController::with_external_32kosc(
peripherals.gclk,
&mut peripherals.pm,
&mut peripherals.sysctrl,
&mut peripherals.nvmctrl,
);
let pins = bsp::Pins::new(peripherals.port);
let mut red_led: bsp::RedLed = pin_alias!(pins.red_led).into();

let _internal_clock = clocks
.configure_gclk_divider_and_source(ClockGenId::Gclk2, 1, ClockSource::Osc32k, false)
.unwrap();
clocks.configure_standby(ClockGenId::Gclk2, true);

enable_internal_32kosc(&mut peripherals.sysctrl);

// Configure a clock for the EIC peripheral
let gclk2 = clocks.get_gclk(ClockGenId::Gclk2).unwrap();
let eic_clock = clocks.eic(&gclk2).unwrap();

let mut eic = EIC::init(&mut peripherals.pm, eic_clock, peripherals.eic).into_future(Irqs);
let button: Pin<_, PullUpInterrupt> = pins.d10.into();
let mut extint = ExtInt2::new(button, &mut eic);
extint.enable_interrupt_wake();

loop {
// Here we show straight falling edge detection without
extint.wait(Sense::Fall).await;
defmt::info!("Falling edge detected");
red_led.toggle().unwrap();
}
}
Loading