//! Transfer control descriptor. /// Common TCD layout for all eDMA implementations. /// /// Fields may vary. See inline notes. mod common { #[repr(C, align(32))] #[allow(non_snake_case)] pub struct RegisterBlock { pub SADDR: u32, // Signed numbers for offsets / 'last' members intentional. // The hardware treats them as signed numbers. pub SOFF: i16, pub ATTR: u16, pub NBYTES: u32, pub SLAST: i32, pub DADDR: u32, pub DOFF: i16, /// The minor loop channel link field may vary in size /// depending on the implementation. Not worried right /// now, since we don't support minor loop linking. pub CITER: u16, pub DLAST_SGA: i32, /// These fields vary across all of eDMA, eDMA3 and /// eDMA4! /// /// Major loop channel linking field size changes as /// a function of the number of DMA channels. /// /// eDMA and eDMA3 have bandwidth control. eDMA4 has /// transfer mode control for read-only / write-only /// DMA transfers. Field is the same size. /// /// In the low byte, high nibble, eDMA has DONE and /// ACTIVE. eDMA3 and eDMA4 have things we probably don't /// need. Low byte, low nibble is the same. /// /// So we'll need to change how we handle DONE and /// ACTIVE access. They can't always dispatch to this /// register. pub CSR: u16, /// See CITER documentation note about eDMA3 bitfield /// size when minor loop channel linking is enabled. pub BITER: u16, } const _: () = assert!(32 == size_of::()); ral_registers::register! { pub SADDR RW [] } ral_registers::register! { pub SOFF RW [] } ral_registers::register! { pub ATTR RW [ #[doc = "Destination data transfer size"] DSIZE start(0) width(3) RW {} #[doc = "Destination Address Modulo"] DMOD start(3) width(5) RW {} #[doc = "Source data transfer size"] SSIZE start(8) width(3) RW {} #[doc = "Source Address Modulo"] SMOD start(11) width(5) RW {} ] } ral_registers::register! { pub NBYTES RW [] } ral_registers::register! { pub SLAST RW [] } ral_registers::register! { pub DADDR RW [] } ral_registers::register! { pub DOFF RW [] } ral_registers::register! { pub CITER RW [] } ral_registers::register! { pub DLAST_SGA RW [] } ral_registers::register! { pub CSR RW [ START start(0) width(1) RW {} INTMAJOR start(1) width(1) RW {} DREQ start(3) width(1) RW {} ACTIVE start(6) width(1) RW {} DONE start(7) width(1) RW {} ] } ral_registers::register! { pub BITER RW [] } } pub mod edma { pub use super::common::*; } pub mod edma34 { #[repr(C, align(32))] #[allow(non_snake_case)] pub struct RegisterBlock { pub CSR: u32, pub ES: u32, pub INT: u32, pub SBR: u32, pub PRI: u32, pub MUX: u32, /// Available on eDMA4, and reserved on eDMA3. _mattr: u32, pub TCD: super::common::RegisterBlock, _reserved: [u8; 0x1_0000 - (4 * 8 + size_of::())], } const _: () = assert!(core::mem::offset_of!(RegisterBlock, TCD) == 0x20); const _: () = assert!(size_of::() == 0x1_0000); ral_registers::register! { pub CSR RW [ ACTIVE start(31) width(1) RW {} DONE start(30) width(1) RW {} ERQ start(0) width(1) RW {} ] } ral_registers::register! { pub SBR RW [ EMI start(16) width(1) RW {} PAL start(15) width(1) RW {} SEC start(14) width(1) RW {} ] } ral_registers::register! { pub INT RW [] } ral_registers::register! { pub ES RW [ ERR start(31) width(1) RW {} ] } ral_registers::register! { pub MUX RW [ SRC start(0) width(6) RW {} ] } #[allow(non_snake_case)] pub mod TCD { pub use crate::tcd::common::{ ATTR, BITER, CITER, DADDR, DLAST_SGA, DOFF, NBYTES, SADDR, SLAST, SOFF, }; pub mod CSR { pub use crate::tcd::common::CSR::{DREQ, INTMAJOR, START, access}; } } }