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

New interrupt bindings #709

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
9c35adf
Implement async timer as proof of concept (#5)
jbeaurivage May 7, 2022
f797143
Remove embassy stuff. Working timer implementation
jbeaurivage Oct 20, 2022
d89b431
Remove async example from feather_m4. Fill this in later.
jbeaurivage Oct 20, 2022
86bbf71
Try implementing async I2C (#6)
jbeaurivage Oct 22, 2022
6e98557
Implement async UART driver (#7)
jbeaurivage Oct 24, 2022
c1ad696
Improve naming convention, implement embedded_hal_async DelayUs for T…
jbeaurivage Oct 24, 2022
ec6dcb9
Minor fixes
jbeaurivage Oct 24, 2022
b4e0b56
Async dma (#8)
jbeaurivage Oct 26, 2022
b18ed67
Async SPI and SPI-DMA transfers
jbeaurivage Oct 27, 2022
2722f43
UART-DMA transfers
jbeaurivage Oct 28, 2022
e750067
Fix thumbv6m DMAC implementation
jbeaurivage Oct 31, 2022
2f89653
Convenience type definitions for SERCOM
jbeaurivage Oct 31, 2022
0d4e00c
Fix some warnings when dma feature is disabled
jbeaurivage Nov 2, 2022
d71555e
Async EIC implementation: thumbv6m and thumbv7em
jbeaurivage Nov 2, 2022
e625bcf
Async-DMA for thumbv7em targets
jbeaurivage Nov 2, 2022
9596a2b
Rustfmt
jbeaurivage Nov 2, 2022
b4a93e9
feather_m0 async SPI example
jbeaurivage Nov 2, 2022
b2416e3
Implement atsamd-hal-async's digital::Wait for EIC pins
jbeaurivage Nov 2, 2022
b9455ec
Fix compilation with 'async' turned off
jbeaurivage Nov 3, 2022
e359b73
Bring in defmt derive for error types
jbeaurivage Nov 3, 2022
e89b17d
Take all SERCOM interrupts for thumbv7em targets
jbeaurivage Nov 4, 2022
75919bb
thumbv7em: Individual EIC pins take interrupts
jbeaurivage Nov 4, 2022
a842f83
Fix atsamd-hal-async implementations for SPI-DMA and I2C-DMA
jbeaurivage Nov 6, 2022
41e16b8
Fix SPI transfers returning too early
jbeaurivage Nov 7, 2022
91e39e4
Fix write-protected EIC registers for thumbv7em
jbeaurivage Nov 8, 2022
c71000e
Be defensive and reset EIC sense to NONE on complete future
jbeaurivage Nov 8, 2022
4a7eace
Fix broken async SPI transfers.
jbeaurivage Nov 9, 2022
d60017a
Fix SPI-DMA transfers
jbeaurivage Nov 10, 2022
01ce709
Move wait_flags fn in i2c impl
jbeaurivage Dec 23, 2022
30427b3
Fix some errors when merging master
jbeaurivage Feb 26, 2023
c41680a
Upgrade to embedded-hal-async 0.2.0-alpha.0 and fix peripheral features
jbeaurivage Feb 27, 2023
8342996
Cleanup Cargo.tomls, fix async SPI example
jbeaurivage Feb 27, 2023
45f424f
Allow incomplete features on nightly
jbeaurivage Mar 31, 2023
54c1087
Fix interrupt assignment for I2C and SPI
jbeaurivage Mar 31, 2023
b753047
Fix async UART+DMA bugs
jbeaurivage Mar 31, 2023
ac7d449
Update to embedded-hal-async 0.2.0-alpha.1
jbeaurivage May 4, 2023
b4e9fa4
Fix defmt dependency conflict
jbeaurivage May 26, 2023
1bfee3a
Upgrade atsamd-hal nightly
jbeaurivage May 26, 2023
2b3deaf
Fix defmt dependency issue
jbeaurivage Aug 22, 2023
92df527
Fix errors arising from converting to fugit
jbeaurivage Aug 22, 2023
285400d
Upgrade to embedded-hal-async 1.0.0-rc.1
jbeaurivage Oct 25, 2023
360c5cd
Remove nightly feature and upgrade embedded-hal-alpha
jbeaurivage Oct 25, 2023
9be4ad7
Remove all references to nightly feature
jbeaurivage Oct 25, 2023
c2995be
Switch atomic-polyfill to portable-atomic
jbeaurivage Oct 26, 2023
f7afdf3
Replace cortex_m::interrupt::free with critical_section::with
jbeaurivage Nov 15, 2023
f24ed59
Minor DMAC doc adjustments
jbeaurivage Dec 1, 2023
4ce89bb
Fix dependencies
jbeaurivage Dec 1, 2023
4bb9bc6
Begin new interrupt binding scheme
jbeaurivage Nov 30, 2023
751d971
Test with DMAC peripheral
jbeaurivage Nov 30, 2023
cc6e74d
Cleanup and make work for thumbv7 DMAC
jbeaurivage Dec 1, 2023
4d69adb
Fix SERCOM and multiple sources problem. Need to implement thumbv7 DMAC
jbeaurivage Dec 10, 2023
0dc3123
Add multiple interrupt sources to single handler; Fix examples
jbeaurivage Dec 10, 2023
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 boards/feather_m0/.cargo/config
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"
]

[target.thumbv6m-none-eabi]
Expand Down
35 changes: 32 additions & 3 deletions boards/feather_m0/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ version = "0.3"
optional = true

[dev-dependencies]
cortex-m-rtic = "1.0"
rtic = { version = "2.0.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.1"
cortex-m-semihosting = "0.3"
Expand All @@ -48,6 +50,9 @@ nom = { version = "5", default-features = false }
heapless = "0.7"
panic-halt = "0.2"
panic-semihosting = "0.5"
defmt = "0.3"
defmt-rtt = "0.3"
panic-probe = "0.3"

[features]
# ask the HAL to enable atsamd21g support
Expand All @@ -65,8 +70,8 @@ max-channels = ["dma", "atsamd-hal/max-channels"]
# Enable pins for the adalogger SD card reader
adalogger = []
sdmmc = ["embedded-sdmmc", "atsamd-hal/sdmmc"]
rtic = ["atsamd-hal/rtic"]
use_semihosting = []
nightly = []

[profile.dev]
incremental = false
Expand Down Expand Up @@ -135,7 +140,7 @@ required-features = ["adalogger", "usb", "sdmmc", "unproven"]

[[example]]
name = "blinky_rtic"
required-features = ["rtic", "unproven"]
required-features = ["unproven", "nightly"]

[[example]]
name = "uart"
Expand All @@ -144,3 +149,27 @@ required-features = ["dma"]
[[example]]
name = "i2c"
required-features = ["dma"]

[[example]]
name = "async_dmac"
required-features = ["dma", "atsamd-hal/async", "nightly"]

[[example]]
name = "async_timer"
required-features = ["atsamd-hal/async", "nightly"]

[[example]]
name = "async_eic"
required-features = ["atsamd-hal/async", "nightly"]

[[example]]
name = "async_i2c"
required-features = ["dma", "atsamd-hal/async", "nightly"]

[[example]]
name = "async_spi"
required-features = ["dma", "atsamd-hal/async", "nightly"]

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

#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]

use defmt_rtt as _;
use panic_probe as _;

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

#[rtic::app(device = bsp::pac, dispatchers = [I2S])]
mod app {
use bsp::hal;
use feather_m0 as bsp;
use hal::{
clock::GenericClockController,
dmac::{
Ch0, Channel, DmaController, PriorityLevel, ReadyFuture, TriggerAction, TriggerSource,
},
};

#[shared]
struct Shared {}

#[local]
struct Local {
channel: Channel<Ch0, ReadyFuture>,
}

#[init]
fn init(cx: init::Context) -> (Shared, Local) {
let mut peripherals = cx.device;
let _core = cx.core;

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 channel = channels.0.init(PriorityLevel::LVL0);

async_task::spawn().ok();
(Shared {}, Local { channel })
}

#[task(local = [channel])]
async fn async_task(cx: async_task::Context) {
let channel = cx.local.channel;

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

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

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

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

loop {
cortex_m::asm::wfi();
}
}
}
85 changes: 85 additions & 0 deletions boards/feather_m0/examples/async_eic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]

use defmt_rtt as _;
use panic_probe as _;

use bsp::{hal, pin_alias};
use feather_m0 as bsp;
use hal::{
clock::{enable_internal_32kosc, ClockGenId, ClockSource, GenericClockController},
ehal::digital::v2::ToggleableOutputPin,
eic::{
pin::{ExtInt2, Sense},
EIC,
},
gpio::{pin::PA18, Pin, PullUpInterrupt},
rtc::{Count32Mode, Rtc},
};

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

#[rtic::app(device = bsp::pac, dispatchers = [I2S])]
mod app {
use super::*;

#[shared]
struct Shared {}

#[local]
struct Local {
extint: ExtInt2<Pin<PA18, PullUpInterrupt>>,
red_led: bsp::RedLed,
}

#[init]
fn init(cx: init::Context) -> (Shared, Local) {
let mut peripherals = cx.device;
let _core = cx.core;

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 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.gclk2();
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();

async_task::spawn().ok();

(Shared {}, Local { extint, red_led })
}

#[task(local = [extint, red_led])]
async fn async_task(cx: async_task::Context) {
let extint = cx.local.extint;
let red_led = cx.local.red_led;

loop {
// Here we show straight falling edge detection without
extint.wait(Sense::FALL).await;
defmt::info!("Falling edge detected");
red_led.toggle().unwrap();
}
}
}
102 changes: 102 additions & 0 deletions boards/feather_m0/examples/async_i2c.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]

use defmt_rtt as _;
use panic_probe as _;

use bsp::hal;
use feather_m0 as bsp;
use fugit::MillisDuration;
use hal::{
clock::GenericClockController,
dmac::{Ch0, DmaController, PriorityLevel},
prelude::*,
sercom::{
i2c::{self, Config, I2cFutureDma},
Sercom3,
},
};
use rtic_monotonics::systick::Systick;

atsamd_hal::bind_interrupts!(struct Irqs {
SERCOM3 => atsamd_hal::sercom::i2c::InterruptHandler<Sercom3>;
DMAC => atsamd_hal::dmac::InterruptHandler;
});

#[rtic::app(device = bsp::pac, dispatchers = [I2S])]
mod app {
use super::*;

#[shared]
struct Shared {}

#[local]
struct Local {
i2c: I2cFutureDma<Config<bsp::I2cPads>, Ch0>,
}

#[init]
fn init(cx: init::Context) -> (Shared, Local) {
let mut peripherals = cx.device;
let _core = cx.core;

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);

// Take SDA and SCL
let (sda, scl) = (pins.sda, pins.scl);

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

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

// Initialize DMA Channel 0
let channel0 = channels.0.init(PriorityLevel::LVL0);

let gclk0 = clocks.gclk0();
let sercom3_clock = &clocks.sercom3_core(&gclk0).unwrap();
let pads = i2c::Pads::new(sda, scl);
let i2c = i2c::Config::new(
&peripherals.PM,
peripherals.SERCOM3,
pads,
sercom3_clock.freq(),
)
.baud(100.kHz())
.enable()
.into_future(Irqs)
.with_dma_channel(channel0);

async_task::spawn().ok();

(Shared {}, Local { i2c })
}

#[task(local = [i2c])]
async fn async_task(cx: async_task::Context) {
let i2c = cx.local.i2c;

loop {
defmt::info!("Sending 0x00 to I2C device...");
// This test is based on the BMP388 barometer. Feel free to use any I2C
// peripheral you have on hand.
i2c.write(0x76, &[0x00]).await.unwrap();

let mut buffer = [0xff; 4];
i2c.read(0x76, &mut buffer).await.unwrap();
defmt::info!("Read buffer: {:#x}", buffer);
Systick::delay(MillisDuration::<u32>::from_ticks(500).convert()).await;
}
}
}
Loading
Loading