Skip to content

Commit

Permalink
sdh: add example for initializing and reading sdcard
Browse files Browse the repository at this point in the history
Signed-off-by: Junxing Zhu <[email protected]>
  • Loading branch information
jakezhu9 committed Dec 7, 2024
1 parent 968b949 commit 90877ac
Show file tree
Hide file tree
Showing 7 changed files with 469 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ members = [
"examples/peripherals/sdcard-demo",
"examples/peripherals/sdcard-gpt-demo",
"examples/peripherals/psram-demo",
"examples/peripherals/sdh-demo",
]
resolver = "2"
31 changes: 31 additions & 0 deletions bouffalo-hal/src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,37 @@ impl Alternate for Spi<1> {
const F: v2::Function = v2::Function::Spi1;
}

#[cfg(feature = "glb-v2")]
impl<GLB: Deref<Target = GlbRegisterBlock>, const N: usize, M: Alternate> Pad<GLB, N, M> {
/// Configures the pin to operate as a SDH pin.
#[inline]
pub fn into_sdh(self) -> Pad<GLB, N, Sdh> {
let config = v2::GpioConfig::RESET_VALUE
.enable_input()
.disable_output()
.enable_schmitt()
.set_pull(v2::Pull::Up)
.set_drive(v2::Drive::Drive0)
.set_function(Sdh::F);
unsafe {
self.base.gpio_config[N].write(config);
}

Pad {
base: self.base,
_mode: PhantomData,
}
}
}

/// SD Host mode (type state).
pub struct Sdh;

impl Alternate for Sdh {
#[cfg(feature = "glb-v2")]
const F: v2::Function = v2::Function::Sdh;
}

impl<GLB: Deref<Target = GlbRegisterBlock>, const N: usize, M: Alternate> Pad<GLB, N, M> {
/// Configures the pin to operate as a pull up output pin.
#[inline]
Expand Down
19 changes: 19 additions & 0 deletions examples/peripherals/sdh-demo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "sdh-demo"
version = "0.1.0"
edition = "2021"
publish = false

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bouffalo-hal = { path = "../../../bouffalo-hal", features = ["bl808"] }
bouffalo-rt = { path = "../../../bouffalo-rt", features = ["bl808-dsp"] }
panic-halt = "1.0.0"
embedded-time = "0.12.1"
embedded-io = "0.6.1"
embedded-sdmmc = "0.8.1"

[[bin]]
name = "sdh-demo"
test = false
8 changes: 8 additions & 0 deletions examples/peripherals/sdh-demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
psram demo

Build this example with:

```
rustup target install riscv64imac-unknown-none-elf
cargo build --target riscv64imac-unknown-none-elf --release -p sdh-demo
```
3 changes: 3 additions & 0 deletions examples/peripherals/sdh-demo/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("cargo:rustc-link-arg=-Tbouffalo-rt.ld");
}
93 changes: 93 additions & 0 deletions examples/peripherals/sdh-demo/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#![no_std]
#![no_main]

use core::{arch::asm, ptr};

use bouffalo_hal::{prelude::*, uart::Config};
use bouffalo_rt::{entry, Clocks, Peripherals};
use embedded_sdmmc::{Block, BlockCount, BlockDevice, BlockIdx, VolumeManager};
use embedded_time::rate::*;
use panic_halt as _;
use sdh::*;

mod sdh;

struct MyTimeSource {}

impl embedded_sdmmc::TimeSource for MyTimeSource {
fn get_timestamp(&self) -> embedded_sdmmc::Timestamp {
// TODO
embedded_sdmmc::Timestamp::from_calendar(2023, 1, 1, 0, 0, 0).unwrap()
}
}

#[entry]
fn main(p: Peripherals, c: Clocks) -> ! {
// light up led
let mut led = p.gpio.io8.into_floating_output();
let mut led_state = PinState::Low;
led.set_state(led_state).ok();

// init serial
let tx = p.gpio.io14.into_uart();
let rx = p.gpio.io15.into_uart();
let sig2 = p.uart_muxes.sig2.into_transmit::<0>();
let sig3 = p.uart_muxes.sig3.into_receive::<0>();

let config = Config::default().set_baudrate(2000000.Bd());
let mut serial = p.uart0.freerun(config, ((tx, sig2), (rx, sig3)), &c);

writeln!(serial, "Welcome to sdh-demo!").ok();

// sdh gpio init
p.gpio.io0.into_sdh();
p.gpio.io1.into_sdh();
p.gpio.io2.into_sdh();
p.gpio.io3.into_sdh();
p.gpio.io4.into_sdh();
p.gpio.io5.into_sdh();

// sdh init
let sdcard = sdh_init(&mut serial);
let time_source = MyTimeSource {};
let mut volume_mgr = VolumeManager::new(sdcard, time_source);
let volume_res = volume_mgr.open_raw_volume(embedded_sdmmc::VolumeIdx(0));
if let Err(e) = volume_res {
writeln!(serial, "Failed to open volume: {:?}", e).ok();
loop {}
}
let volume0 = volume_res.unwrap();
let root_dir = volume_mgr.open_root_dir(volume0).unwrap();

volume_mgr
.iterate_dir(root_dir, |entry| {
writeln!(serial, "Entry: {:?}", entry).ok();
})
.unwrap();

volume_mgr.close_dir(root_dir).unwrap();

loop {
led.set_state(led_state).ok();
led_state = !led_state;
sleep_ms(1000);
}
}

#[inline]
pub(crate) fn set_bits(val: u32, pos: u32, len: u32, val_in: u32) -> u32 {
let mask = ((1 << len) - 1) << pos;
(val & !mask) | ((val_in << pos) & mask)
}

#[inline]
pub(crate) fn is_bit_set(val: u32, pos: u32) -> bool {
(val & (1 << pos)) != 0
}

#[inline]
pub(crate) fn sleep_ms(n: u32) {
for _ in 0..n * 125 {
unsafe { asm!("nop") }
}
}
Loading

0 comments on commit 90877ac

Please sign in to comment.