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 71 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
8f3b47b
Add ADC sample settings
rnd-ash Jan 10, 2025
f18b0df
Begin constructing an async ADC concept for D5X
rnd-ash Jan 15, 2025
8791027
Draft up new ADC API
rnd-ash Jan 20, 2025
45151bb
Test implementation of async read for ADC
rnd-ash Jan 20, 2025
77ef9a0
Resolve rest of the adc read future
rnd-ash Jan 20, 2025
5b9ba80
Move to type based ADC implementation
rnd-ash Jan 21, 2025
aec6b6b
Broken read_blocking implementation
rnd-ash Jan 21, 2025
60318cd
Begin implementing async reading ADC
rnd-ash Jan 22, 2025
65d30f0
Automatically convert pins to correct mode in with_pins
jbeaurivage Jan 21, 2025
0371cf2
Remove explicit reference to a chip in favor of PAC
jbeaurivage Jan 21, 2025
b4a2bde
Split async and sync ADC into different implementations
rnd-ash Jan 22, 2025
36c8701
Clean up ADC
rnd-ash Jan 22, 2025
3566693
Add inlines everywhere
jbeaurivage Jan 22, 2025
ea1569c
Add wait_flags method and do some extra cleanup
jbeaurivage Jan 22, 2025
0d3bfce
Add blocking and async buffered read methods
jbeaurivage Jan 22, 2025
0c0593c
Derive debug for Adc Error
rnd-ash Jan 22, 2025
3580e53
Fix ADC read_buffer not ever starting
rnd-ash Jan 22, 2025
5acd430
Fix ADC reading blocking buffer always returning BufferOverrun
rnd-ash Jan 22, 2025
eaf1d2d
Implement more ADCSettings
rnd-ash Jan 22, 2025
c7c0425
Add in temperature calibration parameters to calibration
rnd-ash Jan 22, 2025
050c73a
Add in CPU Temperature reading
rnd-ash Jan 23, 2025
32ac4da
Add CPU internal sensors reading, and setting VREF for adc
rnd-ash Jan 23, 2025
967e7a7
Restrict internal CPU sensors to primary CPU ADC
rnd-ash Jan 23, 2025
403724e
Remove breaking comments in Cargo.toml
rnd-ash Jan 23, 2025
79193bd
Allow blocking methods on async-enabled ADCs
jbeaurivage Jan 22, 2025
dc4b83d
Derive defmt::Format for error type
jbeaurivage Jan 22, 2025
229e704
Remove duplicate methods
jbeaurivage Jan 23, 2025
0988b38
ADC: Add support for samd21 line
rnd-ash Jan 23, 2025
375e2d0
Remove curiosity nano reference
rnd-ash Jan 24, 2025
41b2c8c
Make names more consistent with the rest of the crate
rnd-ash Jan 27, 2025
af9f15e
samd21 - Fix ADC results being multiplied by 2x
rnd-ash Jan 27, 2025
1a88b13
Error if ADC is configured for summation/averaging but user has selec…
rnd-ash Jan 27, 2025
132e77d
Improve ADC comments
rnd-ash Jan 31, 2025
42193ae
Resolve clippy warnings
rnd-ash Jan 31, 2025
c149b28
Add ADC Pins for D11
rnd-ash Jan 31, 2025
0be0cd6
Improve imports and hal_cfg usage for ADC
rnd-ash Jan 31, 2025
52f15e2
Leave workspace Cargo.toml unchanged
jbeaurivage Feb 4, 2025
af12b9a
Make good use of the typelevel guarantees provided by clock::v2
jbeaurivage Feb 4, 2025
3e603c6
Remove the need for the Channel machinery
jbeaurivage Feb 4, 2025
ec04b58
D5x - Document TH and TL parameters better
rnd-ash Feb 4, 2025
f9991ac
Improve D11/D21 ADC clocking
jbeaurivage Feb 5, 2025
066051a
Cleanup config type aliases
jbeaurivage Feb 5, 2025
7468e40
Add doc comment for ADC::new (thumbv6)
jbeaurivage Feb 5, 2025
ba31cd0
Simplify some snippets, add missing doc comment, and add missing sync…
jbeaurivage Feb 5, 2025
5cff7ed
Minimal working ADC example for feather_m0
jbeaurivage Feb 5, 2025
87775b6
Fix some bugs in conversion methods
jbeaurivage Feb 5, 2025
b2210b7
Slightly improve docs
jbeaurivage Feb 5, 2025
111b91e
Revert workspace Cargo.toml
jbeaurivage Feb 10, 2025
895e745
Add D11 ADC calibration
rnd-ash Feb 10, 2025
0da7e72
Update T1 BSPs
jbeaurivage Feb 11, 2025
a840d6b
Fix misaligned flash read
ianrrees Feb 16, 2025
1178cbe
Make internal calibration API safer
ianrrees Feb 16, 2025
9a7f7ad
Fix math error in ADC bias calibration
ianrrees Feb 16, 2025
768ca17
Improve ADC reading results by powering down and up ADC
rnd-ash Mar 4, 2025
39f1ec6
Fix fmt and clippy warns
jbeaurivage Feb 11, 2025
fb5a2b7
Start fixing pygamer examples
jbeaurivage Feb 20, 2025
99ffb07
Fix overrun errors on thumbv6 targets
jbeaurivage Mar 4, 2025
0a7f78b
Fix dividers in examples
jbeaurivage Mar 4, 2025
1203d5e
Remove pygamer neopixel examples
rnd-ash Mar 15, 2025
b30de24
Fix Samd21g build
rnd-ash Mar 15, 2025
bc156ed
First round of ADC Doc fixes
rnd-ash Mar 30, 2025
0306288
Construct ADC from ADC Builder
rnd-ash May 1, 2025
36ba224
D5x - Correct all calibration values
rnd-ash May 13, 2025
751ee67
D11 - Correct all calibrations and add temp cals
rnd-ash May 13, 2025
900dafb
Cleanup and finalize ADC
rnd-ash May 13, 2025
ad6974a
Refactor the check_and_clear_flags method
jbeaurivage Apr 16, 2025
5bcf403
Improve, standardize examples and make them more robust
jbeaurivage Apr 16, 2025
cf3accc
Mention that async ADC is supported in repo README
jbeaurivage Apr 16, 2025
e1ec823
Doc and formatting fixes
jbeaurivage May 13, 2025
9279035
Fix warning when building without async feature
ianrrees May 18, 2025
2a07681
Supply vref in SAMD11 adc example
ianrrees May 19, 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
Loading