Basic DMA HAL #19
@ -36,9 +36,12 @@ fn main() -> ! {
|
||||
let mut read_buf: [ChannelValue; 8] = [ChannelValue::default(); 8];
|
||||
loop {
|
||||
let single_value = adc
|
||||
.trigger_and_read_single_channel(va416xx_hal::adc::ChannelSelect::AnIn0)
|
||||
.trigger_and_read_single_channel(va416xx_hal::adc::ChannelSelect::TempSensor)
|
||||
.expect("reading single channel value failed");
|
||||
rprintln!("Read single ADC value on channel 0: {:?}", single_value);
|
||||
rprintln!(
|
||||
"Read single ADC value on temperature sensor channel: {:?}",
|
||||
single_value
|
||||
);
|
||||
let read_num = adc
|
||||
.sweep_and_read_range(0, 7, &mut read_buf)
|
||||
.expect("ADC range read failed");
|
||||
|
@ -10,7 +10,7 @@ use rtt_target::{rprintln, rtt_init_print};
|
||||
use simple_examples::peb1;
|
||||
use va416xx_hal::pac::{self, interrupt};
|
||||
use va416xx_hal::prelude::*;
|
||||
use va416xx_hal::wdt::WdtController;
|
||||
use va416xx_hal::wdt::Wdt;
|
||||
|
||||
static WDT_INTRPT_COUNT: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));
|
||||
|
||||
@ -43,8 +43,7 @@ fn main() -> ! {
|
||||
let mut delay_sysclk = cortex_m::delay::Delay::new(cp.SYST, clocks.apb0().raw());
|
||||
|
||||
let mut last_interrupt_counter = 0;
|
||||
let mut wdt_ctrl =
|
||||
WdtController::start(&mut dp.sysconfig, dp.watch_dog, &clocks, WDT_ROLLOVER_MS);
|
||||
let mut wdt_ctrl = Wdt::start(&mut dp.sysconfig, dp.watch_dog, &clocks, WDT_ROLLOVER_MS);
|
||||
wdt_ctrl.enable_reset();
|
||||
loop {
|
||||
if TEST_MODE != TestMode::AllowReset {
|
||||
|
18
va416xx-hal/CHANGELOG.md
Normal file
18
va416xx-hal/CHANGELOG.md
Normal file
@ -0,0 +1,18 @@
|
||||
Change Log
|
||||
=======
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [unreleased]
|
||||
|
||||
## [v0.1.1] 2024-07-01
|
||||
|
||||
- Documentation improvements
|
||||
- Small fixes and improvements for ADC drivers
|
||||
|
||||
## [v0.1.0] 2024-07-01
|
||||
|
||||
- Initial release with basic HAL drivers
|
@ -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();
|
||||
}
|
||||
|
@ -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::{
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user