From a1529146039e733c37a5b5c3e96e0abce82d1b63 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 9 Jun 2020 23:35:57 +0200 Subject: [PATCH 1/5] sdio: change Adma2Desc32 alignment from 1 to 4 this should not break anything. --- libboard_zynq/src/sdio/adma.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libboard_zynq/src/sdio/adma.rs b/libboard_zynq/src/sdio/adma.rs index bcdc424..18262d7 100644 --- a/libboard_zynq/src/sdio/adma.rs +++ b/libboard_zynq/src/sdio/adma.rs @@ -3,7 +3,7 @@ use super::SDIO; use libcortex_a9::cache; use libregister::RegisterR; -#[repr(C, packed)] +#[repr(C, align(4))] #[derive(Clone, Copy)] pub struct Adma2Desc32 { attribute: u16, -- 2.42.0 From 713b90d43cac59ef71436c4f7d424f75fb578797 Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 10 Jun 2020 00:17:53 +0200 Subject: [PATCH 2/5] sdio: convert Adma2Desc32 to VolatileCells, make ADMA2_DESCR32_TABLE: MaybeUninit --- libboard_zynq/src/sdio/adma.rs | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/libboard_zynq/src/sdio/adma.rs b/libboard_zynq/src/sdio/adma.rs index 18262d7..de5b2ba 100644 --- a/libboard_zynq/src/sdio/adma.rs +++ b/libboard_zynq/src/sdio/adma.rs @@ -1,22 +1,18 @@ /// ADMA library +use core::mem::MaybeUninit; use super::SDIO; use libcortex_a9::cache; -use libregister::RegisterR; +use libregister::{RegisterR, VolatileCell}; #[repr(C, align(4))] -#[derive(Clone, Copy)] pub struct Adma2Desc32 { - attribute: u16, - length: u16, - address: u32, + attribute: VolatileCell, + 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]; +static mut ADMA2_DESCR32_TABLE: MaybeUninit<[Adma2Desc32; 32]> = MaybeUninit::uninit(); #[allow(unused)] const DESC_MAX_LENGTH: u32 = 65536; @@ -32,26 +28,21 @@ 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); - } + self.attribute.set(attribute) } pub fn set_length(&mut self, length: u16) { - unsafe { - core::ptr::write_volatile(&mut self.length as *mut u16, length); - } + self.length.set(length) } pub fn set_address(&mut self, address: u32) { - unsafe { - core::ptr::write_volatile(&mut self.address as *mut u32, address); - } + self.address.set(address) } } +/// Initialize `ADMA2_DESCR32_TABLE` and setup `adma_system_address` pub fn setup_adma2_descr32(sdio: &mut SDIO, blk_cnt: u32, buffer: &[u8]) { - let descr_table = unsafe { &mut ADMA2_DESCR32_TABLE }; + let descr_table = unsafe { &mut *ADMA2_DESCR32_TABLE.as_mut_ptr() }; let blk_size = sdio .regs .block_size_block_count -- 2.42.0 From 284a86ca0960c0283a8dde7ab6eda692a276d564 Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 10 Jun 2020 00:27:57 +0200 Subject: [PATCH 3/5] sdio: turn Adma2Desc32.attribute into a register! --- libboard_zynq/src/sdio/adma.rs | 48 ++++++++++++++-------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/libboard_zynq/src/sdio/adma.rs b/libboard_zynq/src/sdio/adma.rs index de5b2ba..fd85101 100644 --- a/libboard_zynq/src/sdio/adma.rs +++ b/libboard_zynq/src/sdio/adma.rs @@ -2,11 +2,14 @@ use core::mem::MaybeUninit; use super::SDIO; use libcortex_a9::cache; -use libregister::{RegisterR, VolatileCell}; +use libregister::{ + register, register_bit, + RegisterR, RegisterW, RegisterRW, VolatileCell, +}; #[repr(C, align(4))] pub struct Adma2Desc32 { - attribute: VolatileCell, + attribute: Desc32Attribute, length: VolatileCell, address: VolatileCell, } @@ -16,29 +19,12 @@ static mut ADMA2_DESCR32_TABLE: MaybeUninit<[Adma2Desc32; 32]> = MaybeUninit::un #[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) { - self.attribute.set(attribute) - } - - pub fn set_length(&mut self, length: u16) { - self.length.set(length) - } - - pub fn set_address(&mut self, address: u32) { - self.address.set(address) - } -} +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); /// Initialize `ADMA2_DESCR32_TABLE` and setup `adma_system_address` pub fn setup_adma2_descr32(sdio: &mut SDIO, blk_cnt: u32, buffer: &[u8]) { @@ -62,13 +48,17 @@ pub fn setup_adma2_descr32(sdio: &mut SDIO, blk_cnt: u32, buffer: &[u8]) { 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); + 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].set_length(0); + descr_table[desc_num].length.set(0); } - descr_table[total_desc_lines - 1].set_attribute(DESC_TRANS | DESC_VALID | DESC_END); - descr_table[total_desc_lines - 1].set_length( + 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 { -- 2.42.0 From 038be3e583e272a52b9357319d6c48aef6575d6c Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 10 Jun 2020 00:38:59 +0200 Subject: [PATCH 4/5] sdio: move ADMA2_DESCR32_TABLE into SdCard --- libboard_zynq/src/sdio/adma.rs | 86 ++++++++++++++++--------------- libboard_zynq/src/sdio/sd_card.rs | 10 ++-- 2 files changed, 51 insertions(+), 45 deletions(-) diff --git a/libboard_zynq/src/sdio/adma.rs b/libboard_zynq/src/sdio/adma.rs index fd85101..9669f42 100644 --- a/libboard_zynq/src/sdio/adma.rs +++ b/libboard_zynq/src/sdio/adma.rs @@ -14,10 +14,6 @@ pub struct Adma2Desc32 { address: VolatileCell, } -// Default::default() cannot be used as it is not a constant function... -static mut ADMA2_DESCR32_TABLE: MaybeUninit<[Adma2Desc32; 32]> = MaybeUninit::uninit(); - -#[allow(unused)] const DESC_MAX_LENGTH: u32 = 65536; register!(desc32_attribute, Desc32Attribute, VolatileCell, u16); @@ -26,45 +22,53 @@ register_bit!(desc32_attribute, int, 2); register_bit!(desc32_attribute, end, 1); register_bit!(desc32_attribute, valid, 0); -/// Initialize `ADMA2_DESCR32_TABLE` and setup `adma_system_address` -pub fn setup_adma2_descr32(sdio: &mut SDIO, blk_cnt: u32, buffer: &[u8]) { - let descr_table = unsafe { &mut *ADMA2_DESCR32_TABLE.as_mut_ptr() }; - let blk_size = sdio - .regs - .block_size_block_count - .read() - .transfer_block_size() as u32; +pub struct Adma2DescTable(MaybeUninit<[Adma2Desc32; 32]>); - 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; +impl Adma2DescTable { + pub fn new() -> Self { + Adma2DescTable(MaybeUninit::uninit()) + } - 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) + /// Initialize the table and setup `adma_system_address` + pub fn setup(&mut self, sdio: &mut SDIO, blk_cnt: u32, buffer: &[u8]) { + let descr_table = unsafe { &mut *self.0.as_mut_ptr() }; + 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].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, ); - // 0 is the max length (65536) - descr_table[desc_num].length.set(0); + unsafe { + sdio.regs + .adma_system_address + .write(descr_table.as_ptr() as u32); + } + cache::dcci_slice(descr_table); } - 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); } 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, -- 2.42.0 From 0a337aac0029701c0550ca1fe89d39a1a67b632a Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 10 Jun 2020 16:46:22 +0200 Subject: [PATCH 5/5] sdio: fix unsound MaybeUninit usage --- libboard_zynq/src/sdio/adma.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libboard_zynq/src/sdio/adma.rs b/libboard_zynq/src/sdio/adma.rs index 9669f42..7543981 100644 --- a/libboard_zynq/src/sdio/adma.rs +++ b/libboard_zynq/src/sdio/adma.rs @@ -22,16 +22,18 @@ register_bit!(desc32_attribute, int, 2); register_bit!(desc32_attribute, end, 1); register_bit!(desc32_attribute, valid, 0); -pub struct Adma2DescTable(MaybeUninit<[Adma2Desc32; 32]>); +pub struct Adma2DescTable([Adma2Desc32; 32]); impl Adma2DescTable { pub fn new() -> Self { - Adma2DescTable(MaybeUninit::uninit()) + let table = MaybeUninit::zeroed(); + let table = unsafe { table.assume_init() }; + Adma2DescTable(table) } /// Initialize the table and setup `adma_system_address` pub fn setup(&mut self, sdio: &mut SDIO, blk_cnt: u32, buffer: &[u8]) { - let descr_table = unsafe { &mut *self.0.as_mut_ptr() }; + let descr_table = &mut self.0; let blk_size = sdio .regs .block_size_block_count -- 2.42.0