Skip to content

Commit 49b3a4c

Browse files
committed
Hook up sdcard library embedded_sdmmc
1 parent a8debb9 commit 49b3a4c

File tree

4 files changed

+153
-0
lines changed

4 files changed

+153
-0
lines changed

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ embedded-hal = "0.2.3"
1515
nb = "0.1.2"
1616
riscv = "0.6.0"
1717
st7735-lcd = { version = "0.7", optional = true }
18+
embedded-sdmmc = { version = "0.3.0", optional = true }
1819

1920
[dev-dependencies]
2021
riscv-rt = "0.8.0"
@@ -23,6 +24,7 @@ embedded-graphics = "0.6"
2324

2425
[features]
2526
lcd = ["st7735-lcd"]
27+
sdcard = ["embedded-sdmmc"]
2628

2729
[[example]]
2830
name = "display"
@@ -32,6 +34,10 @@ required-features = ["lcd"]
3234
name = "ferris"
3335
required-features = ["lcd"]
3436

37+
[[example]]
38+
name = "sdcard_test"
39+
required-features = ["sdcard"]
40+
3541
[package.metadata.docs.rs]
3642
features = ['lcd']
3743
rustdoc-args = ["--cfg", "docsrs"]

examples/sdcard_test.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
use embedded_sdmmc::{Directory, Volume, VolumeIdx};
5+
6+
use longan_nano::sdcard::SdCard;
7+
use panic_halt as _;
8+
9+
use riscv_rt::entry;
10+
use longan_nano::hal::{pac, prelude::*};
11+
use longan_nano::{sdcard, sprint, sprintln};
12+
13+
#[entry]
14+
fn main() -> ! {
15+
let dp = pac::Peripherals::take().unwrap();
16+
17+
// Configure clocks
18+
let mut rcu = dp.RCU.configure()
19+
.ext_hf_clock(8.mhz())
20+
.sysclk(108.mhz())
21+
.freeze();
22+
23+
let mut afio = dp.AFIO.constrain(&mut rcu);
24+
25+
let gpioa = dp.GPIOA.split(&mut rcu);
26+
longan_nano::stdout::configure(dp.USART0, gpioa.pa9, gpioa.pa10, 115_200.bps(), &mut afio, &mut rcu);
27+
28+
let gpiob = dp.GPIOB.split(&mut rcu);
29+
let mut sdcard = sdcard::configure(dp.SPI1, gpiob, &mut rcu);
30+
31+
sprint!("Initializing SD card ... ");
32+
if let Err(_) = sdcard.device().init() {
33+
sprintln!("Failed to initialize sdcard.");
34+
} else {
35+
sprintln!("OK");
36+
sprint!("SD Card Capacity: ");
37+
if let Ok(size) = sdcard.device().card_size_bytes() {
38+
sprintln!("{} MB", size / 1000 / 1000);
39+
// open the first partition
40+
sprintln!("Partition 0:");
41+
if let Ok(mut volume) = sdcard.get_volume(VolumeIdx(0)) {
42+
// list files in root dir
43+
if let Ok(root_dir) = sdcard.open_root_dir(&volume) {
44+
if let Err(_) = sdcard.iterate_dir(&volume, &root_dir, | entry | {
45+
sprintln!("{: >5}B {}", entry.size, entry.name);
46+
}) {
47+
sprintln!("Error while iterating over files.");
48+
}
49+
if let Ok(_) = sdcard.find_directory_entry(&volume, &root_dir, "W_TST.TXT") {
50+
// if a file with the name W_TST.TXT is present, do a write test
51+
write_test(&mut sdcard, &mut volume, &root_dir);
52+
}
53+
} else {
54+
sprintln!("Could not open root directory.");
55+
}
56+
} else {
57+
sprintln!("Could not open partition 0.");
58+
}
59+
} else {
60+
sprintln!("Failed to read card size.");
61+
}
62+
}
63+
64+
sprintln!("done.");
65+
loop { }
66+
}
67+
68+
fn write_test(sdcard: &mut SdCard, volume: &mut Volume, dir: &Directory) {
69+
sprint!("Write test: ");
70+
if let Ok(mut file) = sdcard.open_file_in_dir(volume, dir, "W_TST.CSV", embedded_sdmmc::Mode::ReadWriteCreateOrTruncate) {
71+
let data = "1,2,3,4,20";
72+
if let Ok(size_written) = sdcard.write(volume, &mut file, data.as_bytes()) {
73+
sprintln!("Success (Wrote {}B)", size_written);
74+
} else {
75+
sprintln!("Failed");
76+
}
77+
if let Err(_) = sdcard.close_file(volume, file) {
78+
sprintln!("Could not close file.");
79+
}
80+
} else {
81+
sprintln!("Could not open file for writing.");
82+
}
83+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ pub use gd32vf103xx_hal as hal;
1010
pub mod lcd;
1111
pub mod led;
1212
pub mod stdout;
13+
pub mod sdcard;

src/sdcard.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//! On-board SD Card Slot
2+
3+
use embedded_hal::digital::v2::OutputPin;
4+
use gd32vf103xx_hal::gpio::gpiob::{PB12, PB13, PB14, PB15, Parts};
5+
use gd32vf103xx_hal::gpio::{Alternate, Floating, Input, Output, PushPull};
6+
use gd32vf103xx_hal::pac::{SPI1};
7+
use gd32vf103xx_hal::rcu::Rcu;
8+
use gd32vf103xx_hal::spi::{Spi, MODE_0};
9+
use gd32vf103xx_hal::time::U32Ext;
10+
use embedded_sdmmc::{Controller, SdMmcSpi, TimeSource, Timestamp};
11+
12+
type SckPin = PB13<Alternate<PushPull>>;
13+
type MisoPin = PB14<Input<Floating>>;
14+
type MosiPin = PB15<Alternate<PushPull>>;
15+
type CsPin = PB12<Output<PushPull>>;
16+
type SPI1Pins = (SckPin, MisoPin, MosiPin);
17+
18+
type Spi1 = Spi<SPI1, SPI1Pins>;
19+
20+
/// A type based on embedded_sdmmc::SdMmcSpi that is used by SdCard.
21+
pub type SdCardSpi = SdMmcSpi<Spi1, CsPin>;
22+
23+
/// A type based on embedded_sdmmc::Controller.
24+
pub type SdCard = Controller<SdCardSpi, FakeTimeSource>;
25+
26+
/// Constructs SD Card driver from the required components.
27+
pub fn configure(spi: SPI1, gpiob: Parts, rcu: &mut Rcu) -> SdCard {
28+
let miso = gpiob.pb14.into_floating_input();
29+
let mosi = gpiob.pb15.into_alternate_push_pull();
30+
let sck = gpiob.pb13.into_alternate_push_pull();
31+
let mut cs = gpiob.pb12.into_push_pull_output();
32+
33+
let spi1 = Spi::spi1(
34+
spi,
35+
(sck, miso, mosi),
36+
MODE_0,
37+
300.khz(), // using 300 kHz here because the sdcard init needs 100 to 400 kHz (see SdMmcSpi.init)
38+
rcu,
39+
);
40+
41+
cs.set_high().unwrap();
42+
43+
let sdmmcspi = SdMmcSpi::new(spi1, cs);
44+
let ctime_source = FakeTimeSource {};
45+
46+
Controller::new(sdmmcspi, ctime_source)
47+
}
48+
49+
/// A fake time source that always returns a date of zero.
50+
pub struct FakeTimeSource {}
51+
52+
impl TimeSource for FakeTimeSource {
53+
fn get_timestamp(&self) -> embedded_sdmmc::Timestamp {
54+
Timestamp {
55+
year_since_1970: 0,
56+
zero_indexed_month: 0,
57+
zero_indexed_day: 0,
58+
hours: 0,
59+
minutes: 0,
60+
seconds: 0,
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)