Skip to content

Commit e73199a

Browse files
bors[bot]olbackrichardeoin
authored
Merge #262 #267
262: Add glue to make embedded-sdmmc work nicely r=richardeoin a=olback It would have been nice to implement `embedded:BlockDevice` directly on `Sdmmc<$SDMMCX>` but that is not possible since `BlockDevice` takes `&self` and the methods that already exist take `&mut self`. 267: USART additions r=richardeoin a=richardeoin Follow on from #261 * Add synchronous flag to serial_unchecked method * Set synchronous bits on USART peripherals only, for others they are reserved * Add builder methods for USART configuration fields * Add an example of synchronous USART operation Co-authored-by: Edwin Svensson <git@olback.net> Co-authored-by: Richard Meadows <962920+richardeoin@users.noreply.github.com>
3 parents 0371abb + d847580 + 131c645 commit e73199a

File tree

5 files changed

+334
-56
lines changed

5 files changed

+334
-56
lines changed

Cargo.toml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ embedded-dma = "0.1.2"
3030
cortex-m = "^0.7.1"
3131
stm32h7 = "^0.14.0"
3232
void = { version = "1.0.2", default-features = false }
33-
cast = { version = "0.2.3", default-features = false }
33+
cast = { version = "0.3.0", default-features = false }
3434
nb = "1.0.0"
3535
paste = "1.0.1"
3636
bare-metal = "1.0.0"
37-
sdio-host = { version = "0.4", optional = true }
37+
sdio-host = { version = "0.5", optional = true }
38+
embedded-sdmmc = { version = "0.3", optional = true }
3839
stm32-fmc = { version = "0.2", optional = true }
3940
synopsys-usb-otg = { version = "^0.2.4", features = ["cortex-m"], optional = true }
4041
embedded-display-controller = { version = "^0.1.0", optional = true }
@@ -88,6 +89,7 @@ ltdc = ["embedded-display-controller"]
8889
quadspi = []
8990
fmc = ["stm32-fmc"]
9091
sdmmc = ["sdio-host"]
92+
sdmmc-fatfs = ["embedded-sdmmc", "sdmmc"]
9193
ethernet = ["smoltcp"]
9294
rtc = ["chrono"]
9395
crc = []
@@ -153,6 +155,10 @@ required-features = ["quadspi", "rm0433"]
153155
name = "sdmmc"
154156
required-features = ["sdmmc", "rm0433"]
155157

158+
[[example]]
159+
name = "sdmmc_fat"
160+
required-features = ["sdmmc", "sdmmc-fatfs", "stm32h747cm7"]
161+
156162
[[example]]
157163
name = "ethernet-stm32h747i-disco"
158164
required-features = ["rt", "stm32h747cm7", "ethernet"]

examples/sdmmc_fat.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#![no_main]
2+
#![no_std]
3+
4+
use {
5+
embedded_sdmmc::{Controller, VolumeIdx},
6+
log,
7+
stm32h7xx_hal::{pac, prelude::*, rcc},
8+
};
9+
10+
#[macro_use]
11+
mod utilities;
12+
13+
// This is just a placeholder TimeSource. In a real world application
14+
// one would probably use the RTC to provide time.
15+
pub struct TimeSource;
16+
17+
impl embedded_sdmmc::TimeSource for TimeSource {
18+
fn get_timestamp(&self) -> embedded_sdmmc::Timestamp {
19+
embedded_sdmmc::Timestamp {
20+
year_since_1970: 0,
21+
zero_indexed_month: 0,
22+
zero_indexed_day: 0,
23+
hours: 0,
24+
minutes: 0,
25+
seconds: 0,
26+
}
27+
}
28+
}
29+
30+
#[cortex_m_rt::entry]
31+
unsafe fn main() -> ! {
32+
utilities::logger::init();
33+
34+
// Get peripherals
35+
let cp = cortex_m::Peripherals::take().unwrap();
36+
let dp = pac::Peripherals::take().unwrap();
37+
38+
// Constrain and Freeze power
39+
let pwr = dp.PWR.constrain();
40+
let pwrcfg = example_power!(pwr).freeze();
41+
42+
// Constrain and Freeze clock
43+
let ccdr = dp
44+
.RCC
45+
.constrain()
46+
.sys_ck(480.mhz())
47+
.pll1_strategy(rcc::PllConfigStrategy::Iterative)
48+
.pll1_q_ck(100.mhz())
49+
.pll2_strategy(rcc::PllConfigStrategy::Iterative)
50+
.pll3_strategy(rcc::PllConfigStrategy::Iterative)
51+
.freeze(pwrcfg, &dp.SYSCFG);
52+
53+
// Get the delay provider.
54+
let mut delay = cp.SYST.delay(ccdr.clocks);
55+
56+
let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB);
57+
let gpiod = dp.GPIOD.split(ccdr.peripheral.GPIOD);
58+
59+
let mut sd = dp.SDMMC2.sdmmc(
60+
(
61+
gpiod.pd6.into_alternate_af11(),
62+
gpiod.pd7.into_alternate_af11(),
63+
gpiob.pb14.into_alternate_af9(),
64+
gpiob.pb15.into_alternate_af9(),
65+
gpiob.pb3.into_alternate_af9(),
66+
gpiob.pb4.into_alternate_af9(),
67+
),
68+
ccdr.peripheral.SDMMC2,
69+
&ccdr.clocks,
70+
);
71+
72+
// Loop until we have a card
73+
loop {
74+
// On most development boards this can be increased up to 50MHz. We choose a
75+
// lower frequency here so that it should work even with flying leads
76+
// connected to a SD card breakout.
77+
match sd.init_card(2.mhz()) {
78+
Ok(_) => break,
79+
Err(err) => {
80+
log::info!("Init err: {:?}", err);
81+
}
82+
}
83+
84+
log::info!("Waiting for card...");
85+
86+
delay.delay_ms(1000u32);
87+
}
88+
89+
// See https://github.com/rust-embedded-community/embedded-sdmmc-rs for docs
90+
// and more examples
91+
92+
let mut sd_fatfs = Controller::new(sd.sdmmc_block_device(), TimeSource);
93+
let sd_fatfs_volume = sd_fatfs.get_volume(VolumeIdx(0)).unwrap();
94+
let sd_fatfs_root_dir = sd_fatfs.open_root_dir(&sd_fatfs_volume).unwrap();
95+
sd_fatfs
96+
.iterate_dir(&sd_fatfs_volume, &sd_fatfs_root_dir, |entry| {
97+
log::info!("{:?}", entry);
98+
})
99+
.unwrap();
100+
sd_fatfs.close_dir(&sd_fatfs_volume, sd_fatfs_root_dir);
101+
102+
loop {
103+
cortex_m::asm::nop()
104+
}
105+
}

examples/serial-advanced.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#![no_main]
2+
#![no_std]
3+
4+
use cortex_m_rt::entry;
5+
#[macro_use]
6+
mod utilities;
7+
use log::info;
8+
9+
use stm32h7xx_hal::{pac, prelude::*, serial::config::Config};
10+
11+
use core::fmt::Write;
12+
13+
#[entry]
14+
fn main() -> ! {
15+
utilities::logger::init();
16+
let dp = pac::Peripherals::take().unwrap();
17+
18+
// Constrain and Freeze power
19+
info!("Setup PWR... ");
20+
let pwr = dp.PWR.constrain();
21+
let pwrcfg = example_power!(pwr).freeze();
22+
23+
// Constrain and Freeze clock
24+
info!("Setup RCC... ");
25+
let rcc = dp.RCC.constrain();
26+
let ccdr = rcc.sys_ck(160.mhz()).freeze(pwrcfg, &dp.SYSCFG);
27+
28+
// Acquire the GPIOC peripheral. This also enables the clock for
29+
// GPIOC in the RCC register.
30+
let gpioc = dp.GPIOC.split(ccdr.peripheral.GPIOC);
31+
32+
let tx = gpioc.pc10.into_alternate_af7();
33+
let rx = gpioc.pc11.into_alternate_af7();
34+
let clk = gpioc.pc12.into_alternate_af7();
35+
36+
info!("");
37+
info!("stm32h7xx-hal example - USART Advanced");
38+
info!("");
39+
40+
// Configure the serial peripheral in synchronous mode
41+
let config = Config::new(115_200.bps()).lastbitclockpulse(true);
42+
let serial = dp
43+
.USART3
44+
.serial((tx, rx, clk), config, ccdr.peripheral.USART3, &ccdr.clocks)
45+
.unwrap();
46+
47+
let (mut tx, _rx) = serial.split();
48+
49+
loop {
50+
// core::fmt::Write is implemented for tx.
51+
writeln!(tx, "Hello, world!").unwrap();
52+
}
53+
}

src/sdmmc.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,54 @@ macro_rules! sdmmc {
11421142
Ok(())
11431143
}
11441144

1145+
#[cfg(feature = "sdmmc-fatfs")]
1146+
pub fn sdmmc_block_device(self) -> SdmmcBlockDevice<Sdmmc<$SDMMCX>> {
1147+
SdmmcBlockDevice {
1148+
sdmmc: core::cell::RefCell::new(self)
1149+
}
1150+
}
1151+
1152+
}
1153+
1154+
#[cfg(feature = "sdmmc-fatfs")]
1155+
impl embedded_sdmmc::BlockDevice for SdmmcBlockDevice<Sdmmc<$SDMMCX>> {
1156+
type Error = Error;
1157+
1158+
fn read(
1159+
&self,
1160+
blocks: &mut [embedded_sdmmc::Block],
1161+
start_block_idx: embedded_sdmmc::BlockIdx,
1162+
_reason: &str,
1163+
) -> Result<(), Self::Error> {
1164+
let start = start_block_idx.0;
1165+
let mut sdmmc = self.sdmmc.borrow_mut();
1166+
for block_idx in start..(start + blocks.len() as u32) {
1167+
sdmmc.read_block(
1168+
block_idx,
1169+
&mut blocks[(block_idx - start) as usize].contents,
1170+
)?;
1171+
}
1172+
Ok(())
1173+
}
1174+
1175+
fn write(
1176+
&self,
1177+
blocks: &[embedded_sdmmc::Block],
1178+
start_block_idx: embedded_sdmmc::BlockIdx,
1179+
) -> Result<(), Self::Error> {
1180+
let start = start_block_idx.0;
1181+
let mut sdmmc = self.sdmmc.borrow_mut();
1182+
for block_idx in start..(start + blocks.len() as u32) {
1183+
sdmmc.write_block(block_idx, &blocks[(block_idx - start) as usize].contents)?;
1184+
}
1185+
Ok(())
1186+
}
1187+
1188+
fn num_blocks(&self) -> Result<embedded_sdmmc::BlockCount, Self::Error> {
1189+
let sdmmc = self.sdmmc.borrow_mut();
1190+
Ok(embedded_sdmmc::BlockCount(sdmmc.card()?.size() as u32 / 512u32))
1191+
}
1192+
11451193
}
11461194
)+
11471195
};
@@ -1238,3 +1286,15 @@ impl Cmd {
12381286
Cmd::new(55, rca, Response::Short)
12391287
}
12401288
}
1289+
1290+
#[cfg(feature = "sdmmc-fatfs")]
1291+
pub struct SdmmcBlockDevice<SDMMC> {
1292+
sdmmc: core::cell::RefCell<SDMMC>,
1293+
}
1294+
1295+
#[cfg(feature = "sdmmc-fatfs")]
1296+
impl<SDMMC> SdmmcBlockDevice<SDMMC> {
1297+
pub fn free(self) -> SDMMC {
1298+
self.sdmmc.into_inner()
1299+
}
1300+
}

0 commit comments

Comments
 (0)