Skip to content

Commit

Permalink
remove bitflags and mask stuff, use struct with bool field instead
Browse files Browse the repository at this point in the history
  • Loading branch information
YruamaLairba committed Jul 23, 2023
1 parent 069c7bd commit 5ea1589
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 51 deletions.
99 changes: 55 additions & 44 deletions src/dma/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
//! transfers, double buffering is supported only for Peripheral To Memory and Memory to Peripheral
//! transfers.

use bitflags::bitflags;
use core::{
fmt::{self, Debug, Formatter},
marker::PhantomData,
Expand Down Expand Up @@ -299,17 +298,6 @@ impl Not for CurrentBuffer {
}
}

bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
/// Type allowing to conveniently listen or unlisten several interrupts at same time.
pub struct DmaCommonInterruptsMask: u8 {
const DIRECT_MODE_ERROR = 1 << 1;
const TRANSFER_ERROR = 1 << 2;
const HALF_TRANSFER = 1 << 3;
const TRANSFER_COMPLETE = 1 << 4;
}
}

/// Structure representing setup of common interrupts.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct DmaCommonInterrupts {
Expand All @@ -319,6 +307,18 @@ pub struct DmaCommonInterrupts {
pub direct_mode_error: bool,
}

impl DmaCommonInterrupts {
/// Return a new DmaCommonInterrupts with all fields set to true.
const fn all() -> Self {
Self {
transfer_complete: true,
half_transfer: true,
transfer_error: true,
direct_mode_error: true,
}
}
}

/// Structure returned by Stream or Transfer all_flags() method.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct DmaFlags {
Expand All @@ -329,6 +329,19 @@ pub struct DmaFlags {
pub fifo_error: bool,
}

impl DmaFlags {
/// Return a new DmaFlags with all fields set to true.
const fn all() -> Self {
Self {
transfer_complete: true,
half_transfer: true,
transfer_error: true,
direct_mode_error: true,
fifo_error: true,
}
}
}

/// Stream on the DMA controller.
pub struct StreamX<DMA, const S: u8> {
_dma: PhantomData<DMA>,
Expand Down Expand Up @@ -538,18 +551,22 @@ where
}

#[inline(always)]
fn listen_common_interrupts(&mut self, mask: DmaCommonInterruptsMask) {
// Note: bitflags doesn't garantee value of unused bit :(
let mask = mask.intersection(DmaCommonInterruptsMask::all()).bits() as u32;
fn listen(&mut self, interrupts: DmaCommonInterrupts) {
let mask = (interrupts.transfer_complete as u32) << 4
| (interrupts.half_transfer as u32) << 3
| (interrupts.transfer_error as u32) << 2
| (interrupts.direct_mode_error as u32) << 1;
unsafe { Self::st() }
.cr
.modify(|r, w| unsafe { w.bits(r.bits() | mask) });
}

#[inline(always)]
fn unlisten_common_interrupts(&mut self, mask: DmaCommonInterruptsMask) {
// Note: bitflags doesn't garantee value of unused bit :(
let mask = mask.intersection(DmaCommonInterruptsMask::all()).bits() as u32;
fn unlisten(&mut self, interrupts: DmaCommonInterrupts) {
let mask = (interrupts.transfer_complete as u32) << 4
| (interrupts.half_transfer as u32) << 3
| (interrupts.transfer_error as u32) << 2
| (interrupts.direct_mode_error as u32) << 1;
unsafe { Self::st() }
.cr
.modify(|r, w| unsafe { w.bits(r.bits() & !mask) });
Expand Down Expand Up @@ -676,16 +693,16 @@ macro_rules! dma_stream {
impl<I: Instance> StreamISR for StreamX<I, $number> where Self: crate::Sealed {

#[inline(always)]
fn clear_all_flags(&mut self) {
fn clear_flags(&mut self, flag: DmaFlags) {
//NOTE(unsafe) Atomic write with no side-effects and we only access the bits
// that belongs to the StreamX
let dma = unsafe { &*I::ptr() };
dma.$ifcr.write(|w| w
.$tcif().set_bit() //Clear transfer complete interrupt flag
.$htif().set_bit() //Clear half transfer interrupt flag
.$teif().set_bit() //Clear transfer error interrupt flag
.$dmeif().set_bit() //Clear direct mode error interrupt flag
.$feif().set_bit() //Clear fifo error interrupt flag
.$tcif().bit(flag.transfer_complete) //Clear transfer complete interrupt flag
.$htif().bit(flag.half_transfer) //Clear half transfer interrupt flag
.$teif().bit(flag.transfer_error) //Clear transfer error interrupt flag
.$dmeif().bit(flag.direct_mode_error) //Clear direct mode error interrupt flag
.$feif().bit(flag.fifo_error) //Clear fifo error interrupt flag
);
}

Expand Down Expand Up @@ -1045,18 +1062,12 @@ fn stream_disable<T: Stream>(stream: &mut T) {
if stream.is_enabled() {
// Aborting an on-going transfer might cause interrupts to fire, disable
let interrupts = stream.common_interrupts();
stream.unlisten_common_interrupts(DmaCommonInterruptsMask::all());
stream.unlisten(DmaCommonInterrupts::all());
unsafe { stream.disable() };
while stream.is_enabled() {}

stream.clear_all_flags();
let mut interrupts_mask = DmaCommonInterruptsMask::empty();
use DmaCommonInterruptsMask as Mask;
interrupts_mask.set(Mask::TRANSFER_COMPLETE, interrupts.transfer_complete);
interrupts_mask.set(Mask::HALF_TRANSFER, interrupts.half_transfer);
interrupts_mask.set(Mask::TRANSFER_ERROR, interrupts.transfer_error);
interrupts_mask.set(Mask::DIRECT_MODE_ERROR, interrupts.direct_mode_error);
stream.listen_common_interrupts(interrupts_mask);
stream.clear_flags(DmaFlags::all());
stream.listen(interrupts);
}
}

Expand Down Expand Up @@ -1495,7 +1506,7 @@ where
pub fn release(mut self) -> (STREAM, PERIPHERAL, BUF, Option<BUF>) {
stream_disable(&mut self.stream);
compiler_fence(Ordering::SeqCst);
self.stream.clear_all_flags();
self.stream.clear_flags(DmaFlags::all());

unsafe {
let stream = ptr::read(&self.stream);
Expand All @@ -1515,7 +1526,7 @@ where
/// Clear all interrupts flags for the DMA stream.
#[inline(always)]
pub fn clear_all_flags(&mut self) {
self.stream.clear_all_flags();
self.stream.clear_flags(DmaFlags::all());
}

/// Clear transfer complete interrupt (tcif) for the DMA stream.
Expand Down Expand Up @@ -1612,7 +1623,7 @@ where
_ => DmaDataSize::Word,
};

stream.clear_all_flags();
stream.clear_flags(DmaFlags::all());
stream.set_priority(config.priority);
// NOTE(unsafe) These values are correct because of the invariants of PeriAddress
unsafe {
Expand All @@ -1622,14 +1633,14 @@ where
stream.set_memory_increment(config.memory_increment);
stream.set_peripheral_increment(config.peripheral_increment);

use DmaCommonInterruptsMask as Mask;
let mut interrupts_mask = Mask::empty();
interrupts_mask.set(Mask::TRANSFER_COMPLETE, config.transfer_complete_interrupt);
interrupts_mask.set(Mask::HALF_TRANSFER, config.half_transfer_interrupt);
interrupts_mask.set(Mask::TRANSFER_ERROR, config.transfer_error_interrupt);
interrupts_mask.set(Mask::DIRECT_MODE_ERROR, config.direct_mode_error_interrupt);
stream.unlisten_common_interrupts(Mask::all());
stream.listen_common_interrupts(interrupts_mask);
let interrupts = DmaCommonInterrupts {
transfer_complete: config.transfer_complete_interrupt,
half_transfer: config.half_transfer_interrupt,
transfer_error: config.transfer_error_interrupt,
direct_mode_error: config.direct_mode_error_interrupt,
};
stream.unlisten(DmaCommonInterrupts::all());
stream.listen(interrupts);
if config.fifo_error_interrupt {
stream.listen_fifo_error();
} else {
Expand Down
12 changes: 5 additions & 7 deletions src/dma/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub trait SafePeripheralRead {}
/// Trait for DMA stream interrupt handling.
pub trait StreamISR: crate::Sealed {
/// Clear all interrupts flags for the DMA stream.
fn clear_all_flags(&mut self);
fn clear_flags(&mut self, flags: DmaFlags);

/// Clear transfer complete interrupt (tcif) for the DMA stream.
fn clear_transfer_complete(&mut self);
Expand Down Expand Up @@ -149,13 +149,11 @@ pub trait Stream: StreamISR + crate::Sealed {
/// Set the flow controller (pfctrl).
fn set_flow_controller(&mut self, value: DmaFlowController);

/// Enable several interrupts using a mask. Modify only interrupts with their bits set in the
/// mask
fn listen_common_interrupts(&mut self, mask: DmaCommonInterruptsMask);
/// Enable several interrupts. Modify only interrupts set to `true` in the DmaCommonInterrupts
fn listen(&mut self, interrupts: DmaCommonInterrupts);

/// Disable several interrupts using a mask. Modify only interrupts with their bits set in the
/// mask
fn unlisten_common_interrupts(&mut self, mask: DmaCommonInterruptsMask);
/// Disable several interrupts. Modify only interrupts set to `true` in the DmaCommonInterrupts
fn unlisten(&mut self, interrupts: DmaCommonInterrupts);

/// Convenience method to get the value of several interrupts of the DMA stream. The order of the
/// returns are: `transfer_complete`, `half_transfer`, `transfer_error` and `direct_mode_error`
Expand Down

0 comments on commit 5ea1589

Please sign in to comment.