diff --git a/libboard_zynq/src/sdio/adma.rs b/libboard_zynq/src/sdio/adma.rs index bcdc424..7543981 100644 --- a/libboard_zynq/src/sdio/adma.rs +++ b/libboard_zynq/src/sdio/adma.rs @@ -1,89 +1,76 @@ /// ADMA library +use core::mem::MaybeUninit; use super::SDIO; use libcortex_a9::cache; -use libregister::RegisterR; +use libregister::{ + register, register_bit, + RegisterR, RegisterW, RegisterRW, VolatileCell, +}; -#[repr(C, packed)] -#[derive(Clone, Copy)] +#[repr(C, align(4))] pub struct Adma2Desc32 { - attribute: u16, - length: u16, - address: u32, + attribute: Desc32Attribute, + length: VolatileCell, + address: VolatileCell, } -// Default::default() cannot be used as it is not a constant function... -static mut ADMA2_DESCR32_TABLE: [Adma2Desc32; 32] = [Adma2Desc32 { - attribute: 0, - length: 0, - address: 0, -}; 32]; - -#[allow(unused)] const DESC_MAX_LENGTH: u32 = 65536; -#[allow(unused)] -const DESC_TRANS: u16 = 0x2 << 4; -#[allow(unused)] -const DESC_INT: u16 = 0x1 << 2; -#[allow(unused)] -const DESC_END: u16 = 0x1 << 1; -#[allow(unused)] -const DESC_VALID: u16 = 0x1 << 0; -#[allow(unused)] -impl Adma2Desc32 { - pub fn set_attribute(&mut self, attribute: u16) { - unsafe { - core::ptr::write_volatile(&mut self.attribute as *mut u16, attribute); - } +register!(desc32_attribute, Desc32Attribute, VolatileCell, u16); +register_bit!(desc32_attribute, trans, 5); +register_bit!(desc32_attribute, int, 2); +register_bit!(desc32_attribute, end, 1); +register_bit!(desc32_attribute, valid, 0); + +pub struct Adma2DescTable([Adma2Desc32; 32]); + +impl Adma2DescTable { + pub fn new() -> Self { + let table = MaybeUninit::zeroed(); + let table = unsafe { table.assume_init() }; + Adma2DescTable(table) } - pub fn set_length(&mut self, length: u16) { - unsafe { - core::ptr::write_volatile(&mut self.length as *mut u16, length); - } - } + /// Initialize the table and setup `adma_system_address` + pub fn setup(&mut self, sdio: &mut SDIO, blk_cnt: u32, buffer: &[u8]) { + let descr_table = &mut self.0; + let blk_size = sdio + .regs + .block_size_block_count + .read() + .transfer_block_size() as u32; - pub fn set_address(&mut self, address: u32) { - unsafe { - core::ptr::write_volatile(&mut self.address as *mut u32, address); + let total_desc_lines = if blk_size * blk_cnt < DESC_MAX_LENGTH { + 1 + } else { + blk_size * blk_cnt / DESC_MAX_LENGTH + + if (blk_size * blk_cnt) % DESC_MAX_LENGTH == 0 { + 0 + } else { + 1 + } + } as usize; + + let ptr = buffer.as_ptr() as u32; + for desc_num in 0..total_desc_lines { + descr_table[desc_num].address.set(ptr + (desc_num as u32) * DESC_MAX_LENGTH); + descr_table[desc_num].attribute.write( + Desc32Attribute::zeroed() + .trans(true) + .valid(true) + ); + // 0 is the max length (65536) + descr_table[desc_num].length.set(0); } + descr_table[total_desc_lines - 1].attribute.modify(|_, w| w.end(true)); + descr_table[total_desc_lines - 1].length.set( + (blk_cnt * blk_size - ((total_desc_lines as u32) - 1) * DESC_MAX_LENGTH) as u16, + ); + unsafe { + sdio.regs + .adma_system_address + .write(descr_table.as_ptr() as u32); + } + cache::dcci_slice(descr_table); } } - -pub fn setup_adma2_descr32(sdio: &mut SDIO, blk_cnt: u32, buffer: &[u8]) { - let descr_table = unsafe { &mut ADMA2_DESCR32_TABLE }; - let blk_size = sdio - .regs - .block_size_block_count - .read() - .transfer_block_size() as u32; - - let total_desc_lines = if blk_size * blk_cnt < DESC_MAX_LENGTH { - 1 - } else { - blk_size * blk_cnt / DESC_MAX_LENGTH - + if (blk_size * blk_cnt) % DESC_MAX_LENGTH == 0 { - 0 - } else { - 1 - } - } as usize; - - let ptr = buffer.as_ptr() as u32; - for desc_num in 0..total_desc_lines { - descr_table[desc_num].set_address(ptr + (desc_num as u32) * DESC_MAX_LENGTH); - descr_table[desc_num].set_attribute(DESC_TRANS | DESC_VALID); - // 0 is the max length (65536) - descr_table[desc_num].set_length(0); - } - descr_table[total_desc_lines - 1].set_attribute(DESC_TRANS | DESC_VALID | DESC_END); - descr_table[total_desc_lines - 1].set_length( - (blk_cnt * blk_size - ((total_desc_lines as u32) - 1) * DESC_MAX_LENGTH) as u16, - ); - unsafe { - sdio.regs - .adma_system_address - .write(descr_table.as_ptr() as u32); - } - cache::dcci_slice(descr_table); -} diff --git a/libboard_zynq/src/sdio/sd_card.rs b/libboard_zynq/src/sdio/sd_card.rs index 0826574..d817f27 100644 --- a/libboard_zynq/src/sdio/sd_card.rs +++ b/libboard_zynq/src/sdio/sd_card.rs @@ -1,4 +1,4 @@ -use super::{adma::setup_adma2_descr32, cmd, CardType, CmdTransferError, SDIO}; +use super::{adma::Adma2DescTable, cmd, CardType, CmdTransferError, SDIO}; use libcortex_a9::cache; use libregister::{RegisterR, RegisterRW, RegisterW}; use log::debug; @@ -25,6 +25,7 @@ enum CardVersion { pub struct SdCard { sdio: SDIO, + adma2_desc_table: Adma2DescTable, card_version: CardVersion, hcs: bool, card_id: [u32; 4], @@ -165,6 +166,7 @@ impl SdCard { }; let mut _self = SdCard { sdio, + adma2_desc_table: Adma2DescTable::new(), card_version: CardVersion::SdVer1, hcs: false, card_id: [0, 0, 0, 0], @@ -203,7 +205,7 @@ impl SdCard { self.sdio.set_block_size(512)?; } - setup_adma2_descr32(&mut self.sdio, block_cnt as u32, buffer); + self.adma2_desc_table.setup(&mut self.sdio, block_cnt as u32, buffer); // invalidate D cache, required for ZC706, not sure for Cora Z7 10 cache::dcci_slice(buffer); @@ -256,7 +258,7 @@ impl SdCard { self.sdio.set_block_size(512)?; } - setup_adma2_descr32(&mut self.sdio, block_cnt as u32, buffer); + self.adma2_desc_table.setup(&mut self.sdio, block_cnt as u32, buffer); // invalidate D cache, required for ZC706, not sure for Cora Z7 10 cache::dcci_slice(buffer); @@ -303,7 +305,7 @@ impl SdCard { .block_size_block_count .modify(|_, w| w.transfer_block_size(blk_size)); - setup_adma2_descr32(&mut self.sdio, blk_cnt as u32, buf); + self.adma2_desc_table.setup(&mut self.sdio, blk_cnt as u32, buf); cache::dcci_slice(buf); self.sdio.cmd_transfer_with_mode( ACMD51,