Skip to content

New ADC V2 with Async support #814

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

Open
wants to merge 89 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
e0db457
Allow delay to be constructed with source (Clock V2)
rnd-ash Dec 10, 2024
29168c7
Fix compile tests and restrict source to Gclk0
rnd-ash Dec 10, 2024
d8056c1
Fix compile for sam51
rnd-ash Jan 6, 2025
ca1e486
Cargo fmt
rnd-ash Jan 6, 2025
d7ce590
Merge branch 'atsamd-rs:master' into master
rnd-ash Jan 7, 2025
5dd776b
Add ADC sample settings
rnd-ash Jan 10, 2025
8edb4db
Merge branch 'atsamd-rs:master' into adc_v2
rnd-ash Jan 14, 2025
53818c7
Begin constructing an async ADC concept for D5X
rnd-ash Jan 15, 2025
7e06a82
Draft up new ADC API
rnd-ash Jan 20, 2025
f2b6cc8
Test implementation of async read for ADC
rnd-ash Jan 20, 2025
98261d7
Resolve rest of the adc read future
rnd-ash Jan 20, 2025
afc5430
Move to type based ADC implementation
rnd-ash Jan 21, 2025
7c76cb6
Broken read_blocking implementation
rnd-ash Jan 21, 2025
282c02e
Begin implementing async reading ADC
rnd-ash Jan 22, 2025
18cbbfe
Automatically convert pins to correct mode in with_pins
jbeaurivage Jan 21, 2025
ba755bc
Remove explicit reference to a chip in favor of PAC
jbeaurivage Jan 21, 2025
9a0219d
Split async and sync ADC into different implementations
rnd-ash Jan 22, 2025
f00feed
Merge pull request #2 from jbeaurivage/adc_v2-fixes
rnd-ash Jan 22, 2025
fa51270
Clean up ADC
rnd-ash Jan 22, 2025
ebeb28a
Add inlines everywhere
jbeaurivage Jan 22, 2025
f37b36f
Add wait_flags method and do some extra cleanup
jbeaurivage Jan 22, 2025
bf25449
Add blocking and async buffered read methods
jbeaurivage Jan 22, 2025
a9b46f0
Merge pull request #3 from jbeaurivage/adc_v2-fixes
rnd-ash Jan 22, 2025
6bbbfda
Derive debug for Adc Error
rnd-ash Jan 22, 2025
53aafe0
Fix ADC read_buffer not ever starting
rnd-ash Jan 22, 2025
88f74f5
Fix ADC reading blocking buffer always returning BufferOverrun
rnd-ash Jan 22, 2025
53955a6
Implement more ADCSettings
rnd-ash Jan 22, 2025
9262d33
Add in temperature calibration parameters to calibration
rnd-ash Jan 22, 2025
627d9a9
Add in CPU Temperature reading
rnd-ash Jan 23, 2025
d0e5602
Add CPU internal sensors reading, and setting VREF for adc
rnd-ash Jan 23, 2025
61e8fc6
Restrict internal CPU sensors to primary CPU ADC
rnd-ash Jan 23, 2025
6fa6e30
Remove breaking comments in Cargo.toml
rnd-ash Jan 23, 2025
4cf54ef
Allow blocking methods on async-enabled ADCs
jbeaurivage Jan 22, 2025
8914319
Derive defmt::Format for error type
jbeaurivage Jan 22, 2025
a25b15c
Remove duplicate methods
jbeaurivage Jan 23, 2025
eb8b043
Merge pull request #4 from jbeaurivage/adc_v2-fixes
rnd-ash Jan 23, 2025
6cbc27e
ADC: Add support for samd21 line
rnd-ash Jan 23, 2025
7f7002f
Remove curiosity nano reference
rnd-ash Jan 24, 2025
b236399
Make names more consistent with the rest of the crate
rnd-ash Jan 27, 2025
a1e8fb9
samd21 - Fix ADC results being multiplied by 2x
rnd-ash Jan 27, 2025
8e0bda2
Error if ADC is configured for summation/averaging but user has selec…
rnd-ash Jan 27, 2025
17b2aa6
Improve ADC comments
rnd-ash Jan 31, 2025
92fc81d
Resolve clippy warnings
rnd-ash Jan 31, 2025
183d873
Add ADC Pins for D11
rnd-ash Jan 31, 2025
582b554
Improve imports and hal_cfg usage for ADC
rnd-ash Jan 31, 2025
c01f9ed
Leave workspace Cargo.toml unchanged
jbeaurivage Feb 4, 2025
34db6e0
Make good use of the typelevel guarantees provided by clock::v2
jbeaurivage Feb 4, 2025
d7922c1
Remove the need for the Channel machinery
jbeaurivage Feb 4, 2025
5d5f486
Merge pull request #5 from jbeaurivage/adc_v2
rnd-ash Feb 4, 2025
d83129c
Merge branch 'master' into adc_v2
rnd-ash Feb 4, 2025
932b9f6
D5x - Document TH and TL parameters better
rnd-ash Feb 4, 2025
f6571bc
Improve D11/D21 ADC clocking
jbeaurivage Feb 5, 2025
a85b6af
Cleanup config type aliases
jbeaurivage Feb 5, 2025
d0384ab
Add doc comment for ADC::new (thumbv6)
jbeaurivage Feb 5, 2025
2e398ea
Simplify some snippets, add missing doc comment, and add missing sync…
jbeaurivage Feb 5, 2025
ddccfe0
Minimal working ADC example for feather_m0
jbeaurivage Feb 5, 2025
e45049f
Fix some bugs in conversion methods
jbeaurivage Feb 5, 2025
d28c3f0
Slightly improve docs
jbeaurivage Feb 5, 2025
1667fbf
Add D11 ADC calibration
rnd-ash Feb 10, 2025
4303f46
Revert workspace Cargo.toml
jbeaurivage Feb 10, 2025
284110c
Merge branch 'adc_v2' into adc_v2
rnd-ash Feb 11, 2025
f1c4808
Merge pull request #6 from jbeaurivage/adc_v2
rnd-ash Feb 11, 2025
9492091
Update T1 BSPs
jbeaurivage Feb 11, 2025
42d831d
Merge pull request #7 from jbeaurivage/adc_v2
rnd-ash Feb 11, 2025
e42ee42
Fix misaligned flash read
ianrrees Feb 16, 2025
39b984a
Make internal calibration API safer
ianrrees Feb 16, 2025
872e5bf
Fix math error in ADC bias calibration
ianrrees Feb 16, 2025
1adbef7
Merge pull request #8 from jbeaurivage/adc-testing
rnd-ash Feb 20, 2025
cfcedf1
Improve ADC reading results by powering down and up ADC
rnd-ash Mar 4, 2025
e87e875
Merge remote-tracking branch 'refs/remotes/origin/adc_v2' into adc_v2
rnd-ash Mar 4, 2025
5c5cfff
Fix fmt and clippy warns
jbeaurivage Feb 11, 2025
a6d87c6
Start fixing pygamer examples
jbeaurivage Feb 20, 2025
371d802
Fix overrun errors on thumbv6 targets
jbeaurivage Mar 4, 2025
6feda91
Fix dividers in examples
jbeaurivage Mar 4, 2025
9496416
Merge pull request #9 from jbeaurivage/adc_v2_fix_overrun
rnd-ash Mar 5, 2025
1ef46e0
Remove pygamer neopixel examples
rnd-ash Mar 15, 2025
d4117e7
Fix Samd21g build
rnd-ash Mar 15, 2025
cc03084
Merge branch 'master' into adc_v2
rnd-ash Mar 15, 2025
34fc571
First round of ADC Doc fixes
rnd-ash Mar 30, 2025
855d435
Construct ADC from ADC Builder
rnd-ash May 1, 2025
038a11c
D5x - Correct all calibration values
rnd-ash May 13, 2025
36a0849
D11 - Correct all calibrations and add temp cals
rnd-ash May 13, 2025
9e34e18
Cleanup and finalize ADC
rnd-ash May 13, 2025
7f7f5b2
Refactor the check_and_clear_flags method
jbeaurivage Apr 16, 2025
f37c5bf
Improve, standardize examples and make them more robust
jbeaurivage Apr 16, 2025
0b4cd5a
Mention that async ADC is supported in repo README
jbeaurivage Apr 16, 2025
a6cb4de
Merge pull request #10 from jbeaurivage/adc_v2_more-fixes
rnd-ash May 13, 2025
371da32
Doc and formatting fixes
jbeaurivage May 13, 2025
5d5ee9c
Merge pull request #11 from jbeaurivage/adc_v2_more-fixes
rnd-ash May 13, 2025
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
7 changes: 1 addition & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
[workspace]
resolver = "2"
default-members = ["hal"]
members = [
"hal",
"atsamd-hal-macros",
"pac/*",
"boards/*",
]
members = ["hal", "atsamd-hal-macros", "pac/*", "boards/*"]

[profile.dev]
debug = true
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ use the async APIs.
* DMAC
* EIC (GPIO interrupts)
* Timers
* ADC

### Examples

Expand Down
4 changes: 4 additions & 0 deletions boards/feather_m0/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ required-features = ["adalogger", "usb", "sdmmc"]
[[example]]
name = "adc"

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

[[example]]
name = "async_dmac"
required-features = ["dma", "async"]
Expand Down
49 changes: 32 additions & 17 deletions boards/feather_m0/examples/adc.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,56 @@
#![no_std]
#![no_main]

use atsamd_hal::adc::AdcBuilder;
use feather_m0 as bsp;

use bsp::hal;
use bsp::pac;

#[cfg(not(feature = "use_semihosting"))]
use panic_halt as _;
#[cfg(feature = "use_semihosting")]
use panic_semihosting as _;

use cortex_m_semihosting::hprintln;

use bsp::hal;
use bsp::pac;
use feather_m0 as bsp;

use bsp::entry;
use hal::adc::Adc;
use hal::clock::GenericClockController;
use hal::prelude::*;
use bsp::Pins;
use pac::{CorePeripherals, Peripherals};

use hal::{
adc::{Accumulation, Adc, Prescaler, Resolution},
clock::GenericClockController,
};

#[entry]
fn main() -> ! {
let mut peripherals = Peripherals::take().unwrap();
let core = CorePeripherals::take().unwrap();
let _core = CorePeripherals::take().unwrap();

let pins = Pins::new(peripherals.port);

// SAMD21 targets currently don't support clock::v2
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 delay = hal::delay::Delay::new(core.SYST, &mut clocks);
let mut adc = Adc::adc(peripherals.adc, &mut peripherals.pm, &mut clocks);
let mut a0: bsp::A0 = pins.a0.into();
let gclk0 = clocks.gclk0();
let adc_clock = clocks.adc(&gclk0).unwrap();

let mut adc = AdcBuilder::new(Accumulation::single(atsamd_hal::adc::AdcResolution::_12))
.with_clock_cycles_per_sample(5)
// Overruns if clock divider < 128 in debug mode
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we shouldn't re-work the example, so that it's a little more robust - eg maybe just get one sample at a time so that it is impossible to get an overrun scenario. That limitation could motivate using DMA, which I think a lot of practical ADC applications will need to use anyway

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, DMA is my next thing to work on with the ADC generally speaking

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in rnd-ash#10

.with_clock_divider(Prescaler::Div128)
.with_vref(atsamd_hal::adc::Reference::Intvcc0)
.enable(peripherals.adc, &mut peripherals.pm, &adc_clock)
.unwrap();
let mut adc_pin = pins.a0.into_alternate();

loop {
let data: u16 = adc.read(&mut a0).unwrap();
hprintln!("{}", data).ok();
delay.delay_ms(1000u16);
let mut _buffer = [0; 16];
adc.read_buffer(&mut adc_pin, &mut _buffer).unwrap();
#[cfg(feature = "use_semihosting")]
cortex_m_semihosting::hprintln!("Buffer: {:?}", _buffer).unwrap();
}
}
61 changes: 61 additions & 0 deletions boards/feather_m0/examples/async_adc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#![no_std]
#![no_main]

use atsamd_hal::adc::AdcBuilder;
use feather_m0 as bsp;

use bsp::hal;
use bsp::pac;

#[cfg(not(feature = "use_semihosting"))]
use panic_halt as _;
#[cfg(feature = "use_semihosting")]
use panic_semihosting as _;

use bsp::Pins;
use pac::{CorePeripherals, Peripherals};

use hal::{
adc::{Accumulation, Adc, Adc0, Prescaler, Resolution},
clock::GenericClockController,
};

atsamd_hal::bind_interrupts!(struct Irqs {
ADC => atsamd_hal::adc::InterruptHandler<Adc0>;
});

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

let pins = Pins::new(peripherals.port);

// SAMD21 targets currently don't support clock::v2
let mut clocks = GenericClockController::with_external_32kosc(
peripherals.gclk,
&mut peripherals.pm,
&mut peripherals.sysctrl,
&mut peripherals.nvmctrl,
);
let gclk0 = clocks.gclk0();
let adc_clock = clocks.adc(&gclk0).unwrap();

let mut adc = AdcBuilder::new(Accumulation::single(atsamd_hal::adc::AdcResolution::_12))
.with_clock_cycles_per_sample(5)
// Overruns if clock divider < 128 in debug mode
.with_clock_divider(Prescaler::Div128)
.with_vref(atsamd_hal::adc::Reference::Arefa)
.enable(peripherals.adc, &mut peripherals.pm, &adc_clock)
.unwrap()
.into_future(Irqs);

let mut adc_pin = pins.a0.into_alternate();

loop {
let mut _buffer = [0; 16];
adc.read_buffer(&mut adc_pin, &mut _buffer).await.unwrap();
#[cfg(feature = "use_semihosting")]
cortex_m_semihosting::hprintln!("Result: {:?}", &_buffer).unwrap();
}
}
4 changes: 4 additions & 0 deletions boards/feather_m4/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ version = "0.3.1"
[dev-dependencies]
heapless = "0.7"
panic-halt = "0.2"
cortex-m-semihosting = "0.5.0"
panic-semihosting = "0.5"
rtic = {version = "2.1.1", features = ["thumbv7-backend"]}
smart-leds = "0.3"
Expand All @@ -53,6 +54,9 @@ usb = ["atsamd-hal/usb", "usb-device"]
async = ["atsamd-hal/async"]
use_semihosting = []

[[example]]
name = "adc"

[[example]]
name = "blinky_basic"

Expand Down
60 changes: 60 additions & 0 deletions boards/feather_m4/examples/adc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#![no_std]
#![no_main]

use atsamd_hal::adc::AdcBuilder;
use feather_m4 as bsp;

use bsp::hal;
use bsp::pac;

#[cfg(not(feature = "use_semihosting"))]
use panic_halt as _;
#[cfg(feature = "use_semihosting")]
use panic_semihosting as _;

use bsp::entry;
use bsp::Pins;
use pac::{CorePeripherals, Peripherals};

use hal::{
adc::{Accumulation, Adc, Prescaler, Resolution},
clock::v2::{clock_system_at_reset, pclk::Pclk},
};

#[entry]
fn main() -> ! {
let mut peripherals = Peripherals::take().unwrap();
let _core = CorePeripherals::take().unwrap();

let pins = Pins::new(peripherals.port);

let (mut buses, clocks, tokens) = clock_system_at_reset(
peripherals.oscctrl,
peripherals.osc32kctrl,
peripherals.gclk,
peripherals.mclk,
&mut peripherals.nvmctrl,
);

// Enable the ADC0 ABP clock...
let apb_adc0 = buses.apb.enable(tokens.apbs.adc0);
// ...and enable the ADC0 PCLK. Both of these are required for the
// ADC to run.
let (pclk_adc0, _gclk0) = Pclk::enable(tokens.pclks.adc0, clocks.gclk0);

let mut adc = AdcBuilder::new(Accumulation::single(atsamd_hal::adc::AdcResolution::_12))
.with_clock_cycles_per_sample(5)
// Overruns if clock divider < 32 in debug mode
.with_clock_divider(Prescaler::Div32)
.with_vref(atsamd_hal::adc::Reference::Arefa)
.enable(peripherals.adc0, apb_adc0, &pclk_adc0)
.unwrap();
let mut adc_pin = pins.a0.into_alternate();

loop {
let mut _buffer = [0; 16];
adc.read_buffer(&mut adc_pin, &mut _buffer).unwrap();
#[cfg(feature = "use_semihosting")]
cortex_m_semihosting::hprintln!("Result: {:?}", &_buffer);
}
}
4 changes: 4 additions & 0 deletions boards/metro_m4/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ use_semihosting = []
[[example]]
name = "adc"

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

[[example]]
name = "async_dmac"
required-features = ["dma", "async"]
Expand Down
53 changes: 34 additions & 19 deletions boards/metro_m4/examples/adc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![no_std]
#![no_main]

use atsamd_hal::adc::AdcBuilder;
use metro_m4 as bsp;

use bsp::hal;
Expand All @@ -11,35 +12,49 @@ use panic_halt as _;
#[cfg(feature = "use_semihosting")]
use panic_semihosting as _;

use cortex_m_semihosting::hprintln;

use bsp::entry;
use hal::adc::Adc;
use hal::clock::GenericClockController;
use hal::gpio::B;
use hal::prelude::*;
use pac::gclk::pchctrl::Genselect::Gclk11;
use bsp::Pins;
use pac::{CorePeripherals, Peripherals};

use hal::{
adc::{Accumulation, Adc, Prescaler, Resolution},
clock::v2::{clock_system_at_reset, pclk::Pclk},
};

#[entry]
fn main() -> ! {
let mut peripherals = Peripherals::take().unwrap();
let core = CorePeripherals::take().unwrap();
let mut clocks = GenericClockController::with_external_32kosc(
let _core = CorePeripherals::take().unwrap();

let pins = Pins::new(peripherals.port);

let (mut buses, clocks, tokens) = clock_system_at_reset(
peripherals.oscctrl,
peripherals.osc32kctrl,
peripherals.gclk,
&mut peripherals.mclk,
&mut peripherals.osc32kctrl,
&mut peripherals.oscctrl,
peripherals.mclk,
&mut peripherals.nvmctrl,
);
let pins = bsp::Pins::new(peripherals.port);
let mut delay = hal::delay::Delay::new(core.SYST, &mut clocks);
let mut adc0 = Adc::adc0(peripherals.adc0, &mut peripherals.mclk, &mut clocks, Gclk11);
let mut a0 = pins.a0.into_alternate::<B>();

// Enable the ADC0 ABP clock...
let apb_adc0 = buses.apb.enable(tokens.apbs.adc0);
// ...and enable the ADC0 PCLK. Both of these are required for the
// ADC to run.
let (pclk_adc0, _gclk0) = Pclk::enable(tokens.pclks.adc0, clocks.gclk0);

let mut adc = AdcBuilder::new(Accumulation::single(atsamd_hal::adc::AdcResolution::_12))
.with_clock_cycles_per_sample(5)
// Overruns if clock divider < 32 in debug mode
.with_clock_divider(Prescaler::Div32)
.with_vref(atsamd_hal::adc::Reference::Arefa)
.enable(peripherals.adc0, apb_adc0, &pclk_adc0)
.unwrap();
let mut adc_pin = pins.a0.into_alternate();

loop {
let data: u16 = adc0.read(&mut a0).unwrap();
hprintln!("{}", data).ok();
delay.delay_ms(1000u16);
let mut _buffer = [0; 16];
adc.read_buffer(&mut adc_pin, &mut _buffer).unwrap();
#[cfg(feature = "use_semihosting")]
cortex_m_semihosting::hprintln!("Result: {:?}", &_buffer).unwrap();
}
}
Loading