2022-09-28 02:40:05 +10:00
|
|
|
use crate::macros::{pub_const_fn_new_zeroed, u16_bool_field, u16_enum_field};
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
|
|
#[repr(u16)]
|
|
|
|
pub enum DestAddrControl {
|
|
|
|
#[default]
|
|
|
|
Increment = 0 << 5,
|
|
|
|
Decrement = 1 << 5,
|
|
|
|
Fixed = 2 << 5,
|
|
|
|
IncReload = 3 << 5,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
|
|
#[repr(u16)]
|
|
|
|
pub enum SrcAddrControl {
|
|
|
|
#[default]
|
|
|
|
Increment = 0 << 7,
|
|
|
|
Decrement = 1 << 7,
|
|
|
|
Fixed = 2 << 7,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
|
|
#[repr(u16)]
|
|
|
|
pub enum DmaStartTime {
|
|
|
|
#[default]
|
|
|
|
Immediate = 0 << 12,
|
|
|
|
VBlank = 1 << 12,
|
|
|
|
HBlank = 2 << 12,
|
|
|
|
Special = 3 << 12,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
|
|
#[repr(transparent)]
|
|
|
|
pub struct DmaControl(u16);
|
|
|
|
impl DmaControl {
|
|
|
|
pub_const_fn_new_zeroed!();
|
|
|
|
u16_enum_field!(
|
|
|
|
5 - 6: DestAddrControl,
|
|
|
|
dest_addr_control,
|
|
|
|
with_dest_addr_control
|
|
|
|
);
|
|
|
|
u16_enum_field!(
|
|
|
|
7 - 8: SrcAddrControl,
|
|
|
|
src_addr_control,
|
|
|
|
with_src_addr_control
|
|
|
|
);
|
|
|
|
u16_bool_field!(9, repeat, with_repeat);
|
|
|
|
u16_bool_field!(10, transfer_32bit, with_transfer_32bit);
|
|
|
|
u16_enum_field!(12 - 13: DmaStartTime, start_time, with_start_time);
|
|
|
|
u16_bool_field!(14, irq_after, with_irq_after);
|
|
|
|
u16_bool_field!(15, enabled, with_enabled);
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
#[must_use]
|
|
|
|
pub const fn to_u16(self) -> u16 {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
}
|
2022-09-28 11:53:12 +10:00
|
|
|
|
|
|
|
/// Uses `stm` to set all parts of a DMA as a single instruction.
|
|
|
|
///
|
|
|
|
/// * `src` address for the transfer
|
|
|
|
/// * `dest` address for the transfer
|
|
|
|
/// * `count_ctrl` is the count in the low half and control in the upper half
|
|
|
|
/// * `dma_id` is 0, 1, 2, or 3 (this is debug asserted).
|
|
|
|
///
|
|
|
|
/// After setting the DMA, it won't activate for a minimum of 2 CPU cycles.
|
|
|
|
#[inline]
|
|
|
|
pub unsafe fn stm_dma(
|
|
|
|
dma_id: usize, src: *const u8, dest: *mut u8, count_ctrl: u32,
|
|
|
|
) {
|
|
|
|
debug_assert!(dma_id < 4);
|
|
|
|
let dma_addr = 0x0400_00B0 + dma_id * 0xC;
|
|
|
|
core::arch::asm!(
|
|
|
|
"stm r0, {{r1, r2, r3}}",
|
|
|
|
in("r0") dma_addr,
|
|
|
|
in("r1") src,
|
|
|
|
in("r2") dest,
|
|
|
|
in("r3") count_ctrl,
|
|
|
|
options(nostack, preserves_flags)
|
|
|
|
);
|
|
|
|
}
|