Merge branch 'main' into dma-support
Some checks are pending
Rust/va416xx-rs/pipeline/pr-main Build started...

This commit is contained in:
2024-07-03 22:48:33 +02:00
7 changed files with 90 additions and 25 deletions

View File

@ -1,3 +1,9 @@
//! Analog to Digital Converter (ADC) driver.
//!
//! ## Examples
//!
//! - [ADC and DAC example](https://github.com/us-irs/va416xx-rs/blob/main/examples/simple/examples/dac-adc.rs)
//! - [ADC](https://github.com/us-irs/va416xx-rs/blob/main/examples/simple/examples/adc.rs)
use core::marker::PhantomData;
use crate::clock::Clocks;
@ -46,6 +52,8 @@ pub enum ChannelSelect {
}
bitflags::bitflags! {
/// This structure is used by the ADC multi-select API to
/// allow selecting multiple channels in a convenient manner.
pub struct MultiChannelSelect: u16 {
const AnIn0 = 1;
const AnIn1 = 1 << 1;
@ -129,6 +137,18 @@ impl ChannelValue {
pub enum ChannelTagEnabled {}
pub enum ChannelTagDisabled {}
/// ADC driver structure.
///
/// Currently, this structure supports three primary ways to measure channel value(s):
///
/// * Trigger and read a single value
/// * Trigger and read a range of ADC values using the sweep functionality
/// * Trigger and read multiple ADC values using the sweep functionality
///
/// The ADC channel tag feature is enabled or disabled at compile time using the
/// [ChannelTagEnabled] and [ChannelTagDisabled]. The [Adc::new] method returns a driver instance
/// with the channel tag enabled, while the [Adc::new_with_channel_tag] method can be used to
/// return an instance with the channel tag enabled.
pub struct Adc<TagEnabled = ChannelTagDisabled> {
adc: pac::Adc,
phantom: PhantomData<TagEnabled>,
@ -154,34 +174,44 @@ impl Adc<ChannelTagDisabled> {
lower_bound_idx: u8,
upper_bound_idx: u8,
rx_buf: &mut [u16],
) -> Result<(), AdcRangeReadError> {
) -> Result<usize, AdcRangeReadError> {
self.generic_prepare_range_sweep_and_wait_until_ready(
lower_bound_idx,
upper_bound_idx,
rx_buf.len(),
)?;
for i in 0..self.adc.status().read().fifo_entry_cnt().bits() {
let fifo_entry_count = self.adc.status().read().fifo_entry_cnt().bits();
for i in 0..core::cmp::min(fifo_entry_count, rx_buf.len() as u8) {
rx_buf[i as usize] = self.adc.fifo_data().read().bits() as u16 & 0xfff;
}
Ok(())
Ok(fifo_entry_count as usize)
}
/// Perform a sweep for selected ADC channels.
///
/// Returns the number of read values which were written to the passed RX buffer.
pub fn sweep_and_read_multiselect(
&self,
ch_select: MultiChannelSelect,
rx_buf: &mut [u16],
) -> Result<(), BufferTooSmallError> {
) -> Result<usize, BufferTooSmallError> {
self.generic_prepare_multiselect_sweep_and_wait_until_ready(ch_select, rx_buf.len())?;
for i in 0..self.adc.status().read().fifo_entry_cnt().bits() {
let fifo_entry_count = self.adc.status().read().fifo_entry_cnt().bits();
for i in 0..core::cmp::min(fifo_entry_count, rx_buf.len() as u8) {
rx_buf[i as usize] = self.adc.fifo_data().read().bits() as u16 & 0xfff;
}
Ok(())
Ok(fifo_entry_count as usize)
}
pub fn try_read_single_value(&self) -> nb::Result<Option<u16>, ()> {
self.generic_try_read_single_value()
.map(|v| v.map(|v| v & 0xfff))
}
#[inline(always)]
pub fn channel_tag_enabled(&self) -> bool {
false
}
}
impl Adc<ChannelTagEnabled> {
@ -230,17 +260,21 @@ impl Adc<ChannelTagEnabled> {
Ok(fifo_entry_count as usize)
}
/// Perform a sweep for selected ADC channels.
///
/// Returns the number of read values which were written to the passed RX buffer.
pub fn sweep_and_read_multiselect(
&self,
ch_select: MultiChannelSelect,
rx_buf: &mut [ChannelValue],
) -> Result<(), BufferTooSmallError> {
) -> Result<usize, BufferTooSmallError> {
self.generic_prepare_multiselect_sweep_and_wait_until_ready(ch_select, rx_buf.len())?;
for i in 0..self.adc.status().read().fifo_entry_cnt().bits() {
let fifo_entry_count = self.adc.status().read().fifo_entry_cnt().bits();
for i in 0..core::cmp::min(fifo_entry_count, rx_buf.len() as u8) {
rx_buf[i as usize] =
self.create_channel_value(self.adc.fifo_data().read().bits() as u16);
}
Ok(())
Ok(fifo_entry_count as usize)
}
#[inline]
@ -250,6 +284,11 @@ impl Adc<ChannelTagEnabled> {
channel: ChannelSelect::try_from(((raw_value >> 12) & 0xf) as u8).unwrap(),
}
}
#[inline(always)]
pub fn channel_tag_enabled(&self) -> bool {
true
}
}
impl<TagEnabled> Adc<TagEnabled> {
@ -274,11 +313,6 @@ impl<TagEnabled> Adc<TagEnabled> {
self.adc.ctrl().modify(|_, w| w.chan_tag_en().clear_bit());
}
#[inline(always)]
pub fn channel_tag_enabled(&self) -> bool {
self.adc.ctrl().read().chan_tag_en().bit_is_set()
}
#[inline(always)]
pub fn clear_fifo(&self) {
self.adc.fifo_clr().write(|w| unsafe { w.bits(1) });
@ -326,8 +360,6 @@ impl<TagEnabled> Adc<TagEnabled> {
ch_select |= 1 << i;
}
self.generic_trigger_sweep(ch_select);
cortex_m::asm::nop();
cortex_m::asm::nop();
while self.adc.status().read().adc_busy().bit_is_set() {
cortex_m::asm::nop();
}

View File

@ -1,3 +1,8 @@
//! Digital to Analog Converter (DAC) driver.
//!
//! ## Examples
//!
//! - [ADC and DAC example](https://github.com/us-irs/va416xx-rs/blob/main/examples/simple/examples/dac-adc.rs)
use core::ops::Deref;
use crate::{

View File

@ -2,7 +2,7 @@
//!
//! ## Examples
//!
//! TODO.
//! - [Timer MS and Second Tick Example](https://github.com/us-irs/va416xx-rs/blob/main/examples/simple/examples/timer-ticks.rs)
use core::cell::Cell;
use cortex_m::interrupt::Mutex;
@ -459,7 +459,10 @@ unsafe impl TimRegInterface for TimDynRegister {
// Timers
//==================================================================================================
/// Hardware timers
/// Hardware timers.
///
/// These timers also implement the [embedded_hal::delay::DelayNs] trait and can be used to delay
/// with a higher resolution compared to the Cortex-M systick delays.
pub struct CountdownTimer<TIM: ValidTim> {
tim: TimRegister<TIM>,
curr_freq: Hertz,

View File

@ -13,11 +13,16 @@ use crate::{disable_interrupt, enable_interrupt};
pub const WDT_UNLOCK_VALUE: u32 = 0x1ACC_E551;
pub struct WdtController {
/// Watchdog peripheral driver.
pub struct Wdt {
clock_freq: Hertz,
wdt: pac::WatchDog,
}
/// Type alias for backwards compatibility
#[deprecated(since = "0.2.0", note = "Please use `Wdt` instead")]
pub type WdtController = Wdt;
/// Enable the watchdog interrupt
///
/// # Safety
@ -33,7 +38,7 @@ pub fn disable_wdt_interrupts() {
disable_interrupt(pac::Interrupt::WATCHDOG)
}
impl WdtController {
impl Wdt {
pub fn new(
&self,
syscfg: &mut pac::Sysconfig,