aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32h7
diff options
context:
space:
mode:
authorPegasis <[email protected]>2024-05-03 08:12:30 -0400
committerPegasis <[email protected]>2024-05-03 08:14:32 -0400
commit3e87dae578969874d354c538d8c59e7be491933d (patch)
tree614d1fb9146a1650ffe8bb3cc64884a8d46ed9b2 /examples/stm32h7
parent45a2abc392df91ce6963ac0956f48f22bfa1489b (diff)
add example for bdma
Diffstat (limited to 'examples/stm32h7')
-rw-r--r--examples/stm32h7/build.rs30
-rw-r--r--examples/stm32h7/memory.x14
-rw-r--r--examples/stm32h7/src/bin/spi_bdma.rs78
3 files changed, 122 insertions, 0 deletions
diff --git a/examples/stm32h7/build.rs b/examples/stm32h7/build.rs
index 8cd32d7ed..b9bb661f0 100644
--- a/examples/stm32h7/build.rs
+++ b/examples/stm32h7/build.rs
@@ -1,4 +1,34 @@
1//! This build script copies the `memory.x` file from the crate root into
2//! a directory where the linker can always find it at build time.
3//! For many projects this is optional, as the linker always searches the
4//! project root directory -- wherever `Cargo.toml` is. However, if you
5//! are using a workspace or have a more complicated build setup, this
6//! build script becomes required. Additionally, by requesting that
7//! Cargo re-run the build script whenever `memory.x` is changed,
8//! updating `memory.x` ensures a rebuild of the application with the
9//! new memory settings.
10
11use std::env;
12use std::fs::File;
13use std::io::Write;
14use std::path::PathBuf;
15
1fn main() { 16fn main() {
17 // Put `memory.x` in our output directory and ensure it's
18 // on the linker search path.
19 let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
20 File::create(out.join("memory.x"))
21 .unwrap()
22 .write_all(include_bytes!("memory.x"))
23 .unwrap();
24 println!("cargo:rustc-link-search={}", out.display());
25
26 // By default, Cargo will re-run a build script whenever
27 // any file in the project changes. By specifying `memory.x`
28 // here, we ensure the build script is only re-run when
29 // `memory.x` is changed.
30 println!("cargo:rerun-if-changed=memory.x");
31
2 println!("cargo:rustc-link-arg-bins=--nmagic"); 32 println!("cargo:rustc-link-arg-bins=--nmagic");
3 println!("cargo:rustc-link-arg-bins=-Tlink.x"); 33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
4 println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); 34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
diff --git a/examples/stm32h7/memory.x b/examples/stm32h7/memory.x
new file mode 100644
index 000000000..e5ab1f62c
--- /dev/null
+++ b/examples/stm32h7/memory.x
@@ -0,0 +1,14 @@
1MEMORY
2{
3 FLASH : ORIGIN = 0x08000000, LENGTH = 2048K /* BANK_1 + BANK_2 */
4 RAM : ORIGIN = 0x24000000, LENGTH = 512K /* SRAM */
5 RAM_D3 : ORIGIN = 0x38000000, LENGTH = 64K /* SRAM4 */
6}
7
8SECTIONS
9{
10 .ram_d3 :
11 {
12 *(.ram_d3)
13 } > RAM_D3
14} \ No newline at end of file
diff --git a/examples/stm32h7/src/bin/spi_bdma.rs b/examples/stm32h7/src/bin/spi_bdma.rs
new file mode 100644
index 000000000..2fc37fc22
--- /dev/null
+++ b/examples/stm32h7/src/bin/spi_bdma.rs
@@ -0,0 +1,78 @@
1#![no_std]
2#![no_main]
3
4use core::fmt::Write;
5use core::str::from_utf8;
6
7use cortex_m_rt::entry;
8use defmt::*;
9use embassy_executor::Executor;
10use embassy_stm32::mode::Async;
11use embassy_stm32::time::mhz;
12use embassy_stm32::{peripherals, spi, Config};
13use heapless::String;
14use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _};
16
17// Defined in memory.x
18#[link_section = ".ram_d3"]
19static mut RAM_D3: [u8; 64 * 1024] = [0u8; 64 * 1024];
20
21#[embassy_executor::task]
22async fn main_task(mut spi: spi::Spi<'static, peripherals::SPI6, Async>) {
23 let read_buffer = unsafe { &mut RAM_D3[0..128] };
24 let write_buffer = unsafe { &mut RAM_D3[128..256] };
25
26 for n in 0u32.. {
27 let mut write: String<128> = String::new();
28 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
29 let read_buffer = &mut read_buffer[..write.len()];
30 let write_buffer = &mut write_buffer[..write.len()];
31 // copy data to write_buffer which is located in D3 domain, accessable by BDMA
32 write_buffer.clone_from_slice(write.as_bytes());
33
34 spi.transfer(read_buffer, write_buffer).await.ok();
35 info!("read via spi+dma: {}", from_utf8(read_buffer).unwrap());
36 }
37}
38
39static EXECUTOR: StaticCell<Executor> = StaticCell::new();
40
41#[entry]
42fn main() -> ! {
43 info!("Hello World!");
44
45 let mut config = Config::default();
46 {
47 use embassy_stm32::rcc::*;
48 config.rcc.hsi = Some(HSIPrescaler::DIV1);
49 config.rcc.csi = true;
50 config.rcc.pll1 = Some(Pll {
51 source: PllSource::HSI,
52 prediv: PllPreDiv::DIV4,
53 mul: PllMul::MUL50,
54 divp: Some(PllDiv::DIV2),
55 divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz.
56 divr: None,
57 });
58 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
59 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
60 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
61 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
62 config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz
63 config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz
64 config.rcc.voltage_scale = VoltageScale::Scale1;
65 }
66 let p = embassy_stm32::init(config);
67
68 let mut spi_config = spi::Config::default();
69 spi_config.frequency = mhz(1);
70
71 let spi = spi::Spi::new(p.SPI6, p.PA5, p.PA7, p.PA6, p.BDMA_CH1, p.BDMA_CH0, spi_config);
72
73 let executor = EXECUTOR.init(Executor::new());
74
75 executor.run(|spawner| {
76 unwrap!(spawner.spawn(main_task(spi)));
77 })
78}