diff options
| -rwxr-xr-x | ci.sh | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/qspi/mod.rs | 20 | ||||
| -rw-r--r-- | examples/stm32l432/.cargo/config.toml | 13 | ||||
| -rw-r--r-- | examples/stm32l432/Cargo.toml | 30 | ||||
| -rw-r--r-- | examples/stm32l432/README.md | 30 | ||||
| -rw-r--r-- | examples/stm32l432/build.rs | 5 | ||||
| -rw-r--r-- | examples/stm32l432/src/bin/qspi_mmap.rs | 274 |
7 files changed, 373 insertions, 0 deletions
| @@ -231,6 +231,7 @@ cargo batch \ | |||
| 231 | --- build --release --manifest-path examples/stm32l0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32l0 \ | 231 | --- build --release --manifest-path examples/stm32l0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32l0 \ |
| 232 | --- build --release --manifest-path examples/stm32l1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32l1 \ | 232 | --- build --release --manifest-path examples/stm32l1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32l1 \ |
| 233 | --- build --release --manifest-path examples/stm32l4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32l4 \ | 233 | --- build --release --manifest-path examples/stm32l4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32l4 \ |
| 234 | --- build --release --manifest-path examples/stm32l432/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32l432 \ | ||
| 234 | --- build --release --manifest-path examples/stm32l5/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/stm32l5 \ | 235 | --- build --release --manifest-path examples/stm32l5/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/stm32l5 \ |
| 235 | --- build --release --manifest-path examples/stm32u0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32u0 \ | 236 | --- build --release --manifest-path examples/stm32u0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32u0 \ |
| 236 | --- build --release --manifest-path examples/stm32u5/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/stm32u5 \ | 237 | --- build --release --manifest-path examples/stm32u5/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/stm32u5 \ |
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index 3d5b31815..411e533c9 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs | |||
| @@ -201,6 +201,26 @@ impl<'d, T: Instance, M: PeriMode> Qspi<'d, T, M> { | |||
| 201 | T::REGS.fcr().modify(|v| v.set_ctcf(true)); | 201 | T::REGS.fcr().modify(|v| v.set_ctcf(true)); |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | /// Enable memory map mode | ||
| 205 | pub fn enable_memory_map(&mut self, transaction: &TransferConfig) { | ||
| 206 | T::REGS.fcr().modify(|v| { | ||
| 207 | v.set_csmf(true); | ||
| 208 | v.set_ctcf(true); | ||
| 209 | v.set_ctef(true); | ||
| 210 | v.set_ctof(true); | ||
| 211 | }); | ||
| 212 | T::REGS.ccr().write(|v| { | ||
| 213 | v.set_fmode(QspiMode::MemoryMapped.into()); | ||
| 214 | v.set_imode(transaction.iwidth.into()); | ||
| 215 | v.set_instruction(transaction.instruction); | ||
| 216 | v.set_admode(transaction.awidth.into()); | ||
| 217 | v.set_adsize(self.config.address_size.into()); | ||
| 218 | v.set_dmode(transaction.dwidth.into()); | ||
| 219 | v.set_abmode(QspiWidth::NONE.into()); | ||
| 220 | v.set_dcyc(transaction.dummy.into()); | ||
| 221 | }); | ||
| 222 | } | ||
| 223 | |||
| 204 | fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig, data_len: Option<usize>) { | 224 | fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig, data_len: Option<usize>) { |
| 205 | match (transaction.address, transaction.awidth) { | 225 | match (transaction.address, transaction.awidth) { |
| 206 | (Some(_), QspiWidth::NONE) => panic!("QSPI address can't be sent with an address width of NONE"), | 226 | (Some(_), QspiWidth::NONE) => panic!("QSPI address can't be sent with an address width of NONE"), |
diff --git a/examples/stm32l432/.cargo/config.toml b/examples/stm32l432/.cargo/config.toml new file mode 100644 index 000000000..0a42c584b --- /dev/null +++ b/examples/stm32l432/.cargo/config.toml | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
| 2 | # replace STM32F429ZITx with your chip as listed in `probe-rs chip list` | ||
| 3 | #runner = "probe-rs run --chip STM32L475VGT6" | ||
| 4 | #runner = "probe-rs run --chip STM32L475VG" | ||
| 5 | #runner = "probe-rs run --chip STM32L4S5QI" | ||
| 6 | runner = "probe-rs run --chip STM32L432KCUx --connect-under-reset --speed 3300" | ||
| 7 | |||
| 8 | |||
| 9 | [build] | ||
| 10 | target = "thumbv7em-none-eabi" | ||
| 11 | |||
| 12 | [env] | ||
| 13 | DEFMT_LOG = "trace" | ||
diff --git a/examples/stm32l432/Cargo.toml b/examples/stm32l432/Cargo.toml new file mode 100644 index 000000000..460561b36 --- /dev/null +++ b/examples/stm32l432/Cargo.toml | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2021" | ||
| 3 | name = "embassy-stm32l4-examples" | ||
| 4 | version = "0.1.1" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | |||
| 7 | [dependencies] | ||
| 8 | # Change stm32l4s5vi to your chip name, if necessary. | ||
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l432kc", "memory-x", "time-driver-any", "exti", "chrono"] } | ||
| 10 | embassy-sync = { version = "0.6.1", path = "../../embassy-sync", features = [ "defmt" ] } | ||
| 11 | embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = [ "task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt" ] } | ||
| 12 | embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "tick-hz-32_768" ] } | ||
| 13 | defmt = "0.3" | ||
| 14 | defmt-rtt = "0.4" | ||
| 15 | |||
| 16 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | ||
| 17 | cortex-m-rt = "0.7.0" | ||
| 18 | embedded-hal = "0.2.6" | ||
| 19 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | ||
| 20 | embedded-hal-async = { version = "1.0" } | ||
| 21 | embedded-hal-bus = { version = "0.1", features = ["async"] } | ||
| 22 | panic-probe = { version = "0.3", features = ["print-defmt"] } | ||
| 23 | |||
| 24 | [profile.release] | ||
| 25 | debug = 2 | ||
| 26 | |||
| 27 | [[bin]] | ||
| 28 | name = "qspi_mmap" | ||
| 29 | path = "src/bin/qspi_mmap.rs" | ||
| 30 | test = false | ||
diff --git a/examples/stm32l432/README.md b/examples/stm32l432/README.md new file mode 100644 index 000000000..3dac97f03 --- /dev/null +++ b/examples/stm32l432/README.md | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | |||
| 2 | # Examples for STM32L432 family | ||
| 3 | |||
| 4 | Examples in this repo should work with [NUCLEO-L432KC](https://www.st.com/en/evaluation-tools/nucleo-l432kc.html) board. | ||
| 5 | |||
| 6 | Run individual examples with | ||
| 7 | ``` | ||
| 8 | cargo run --bin <module-name> | ||
| 9 | ``` | ||
| 10 | for example | ||
| 11 | ``` | ||
| 12 | cargo run --bin blinky | ||
| 13 | ``` | ||
| 14 | |||
| 15 | |||
| 16 | |||
| 17 | ## Checklist before running examples | ||
| 18 | You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. | ||
| 19 | |||
| 20 | * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L432KCU6 it should be `probe-rs run --chip STM32L432KCUx`. (use `probe-rs chip list` to find your chip) | ||
| 21 | * [ ] Update Cargo.toml to have the correct `embassy-stm32` feature. For example for L432KCU6 it should be `stm32l432kc`. Look in the `Cargo.toml` file of the `embassy-stm32` project to find the correct feature flag for your chip. | ||
| 22 | * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. | ||
| 23 | * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic | ||
| 24 | |||
| 25 | If you are unsure, please drop by the Embassy Matrix chat for support, and let us know: | ||
| 26 | |||
| 27 | * Which example you are trying to run | ||
| 28 | * Which chip and board you are using | ||
| 29 | |||
| 30 | Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org | ||
diff --git a/examples/stm32l432/build.rs b/examples/stm32l432/build.rs new file mode 100644 index 000000000..8cd32d7ed --- /dev/null +++ b/examples/stm32l432/build.rs | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | fn main() { | ||
| 2 | println!("cargo:rustc-link-arg-bins=--nmagic"); | ||
| 3 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | ||
| 4 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
| 5 | } | ||
diff --git a/examples/stm32l432/src/bin/qspi_mmap.rs b/examples/stm32l432/src/bin/qspi_mmap.rs new file mode 100644 index 000000000..86a20eb3d --- /dev/null +++ b/examples/stm32l432/src/bin/qspi_mmap.rs | |||
| @@ -0,0 +1,274 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![allow(dead_code)] | ||
| 4 | /// This example demonstrates how to use the QSPI peripheral in both indirect-mode and memory-mapped mode. | ||
| 5 | /// If you want to test this example, please pay attention to flash pins and check flash device datasheet | ||
| 6 | /// to make sure operations in this example are compatible with your device, especially registers I/O operations. | ||
| 7 | use defmt::info; | ||
| 8 | use embassy_stm32::mode; | ||
| 9 | use embassy_stm32::qspi::enums::{ | ||
| 10 | AddressSize, ChipSelectHighTime, DummyCycles, FIFOThresholdLevel, MemorySize, QspiWidth, | ||
| 11 | }; | ||
| 12 | use embassy_stm32::qspi::{self, Instance, TransferConfig}; | ||
| 13 | pub struct FlashMemory<I: Instance> { | ||
| 14 | qspi: qspi::Qspi<'static, I, mode::Async>, | ||
| 15 | } | ||
| 16 | use embassy_executor::Spawner; | ||
| 17 | use embassy_time::Timer; | ||
| 18 | use {defmt_rtt as _, panic_probe as _}; | ||
| 19 | |||
| 20 | const MEMORY_PAGE_SIZE: usize = 256; | ||
| 21 | const CMD_READ_SR: u8 = 0x05; | ||
| 22 | const CMD_READ_CR: u8 = 0x35; | ||
| 23 | const CMD_QUAD_READ: u8 = 0x6B; | ||
| 24 | const CMD_QUAD_WRITE_PG: u8 = 0x32; | ||
| 25 | const CMD_READ_ID: u8 = 0x9F; | ||
| 26 | const CMD_READ_MID: u8 = 0x90; | ||
| 27 | const CMD_READ_UUID: u8 = 0x4B; | ||
| 28 | const CMD_ENABLE_RESET: u8 = 0x66; | ||
| 29 | const CMD_RESET: u8 = 0x99; | ||
| 30 | const CMD_WRITE_ENABLE: u8 = 0x06; | ||
| 31 | const CMD_SECTOR_ERASE: u8 = 0x20; | ||
| 32 | |||
| 33 | const CMD_WRITE_SR: u8 = 0x01; | ||
| 34 | |||
| 35 | impl<I: Instance> FlashMemory<I> { | ||
| 36 | pub fn new(qspi: qspi::Qspi<'static, I, mode::Async>) -> Self { | ||
| 37 | let mut memory = Self { qspi }; | ||
| 38 | |||
| 39 | memory.reset_memory(); | ||
| 40 | memory.enable_quad(); | ||
| 41 | |||
| 42 | memory | ||
| 43 | } | ||
| 44 | fn enable_quad(&mut self) { | ||
| 45 | let sr = self.read_sr_lsb(); | ||
| 46 | let cr = self.read_sr_msb(); | ||
| 47 | |||
| 48 | self.write_sr(sr, cr | 0x02); | ||
| 49 | } | ||
| 50 | fn read_register(&mut self, cmd: u8) -> u8 { | ||
| 51 | let mut buffer = [0; 1]; | ||
| 52 | let transaction = TransferConfig { | ||
| 53 | iwidth: QspiWidth::SING, | ||
| 54 | awidth: QspiWidth::NONE, | ||
| 55 | dwidth: QspiWidth::SING, | ||
| 56 | instruction: cmd, | ||
| 57 | address: None, | ||
| 58 | dummy: DummyCycles::_0, | ||
| 59 | }; | ||
| 60 | self.qspi.blocking_read(&mut buffer, transaction); | ||
| 61 | buffer[0] | ||
| 62 | } | ||
| 63 | |||
| 64 | fn write_register(&mut self, cmd: u8, value: u8) { | ||
| 65 | let buffer = [value; 1]; | ||
| 66 | let transaction: TransferConfig = TransferConfig { | ||
| 67 | iwidth: QspiWidth::SING, | ||
| 68 | awidth: QspiWidth::NONE, | ||
| 69 | dwidth: QspiWidth::SING, | ||
| 70 | instruction: cmd, | ||
| 71 | address: None, | ||
| 72 | dummy: DummyCycles::_0, | ||
| 73 | }; | ||
| 74 | self.qspi.blocking_write(&buffer, transaction); | ||
| 75 | } | ||
| 76 | pub fn write_sr(&mut self, lsb: u8, msb: u8) { | ||
| 77 | let buffer = [lsb, msb]; | ||
| 78 | let transaction: TransferConfig = TransferConfig { | ||
| 79 | iwidth: QspiWidth::SING, | ||
| 80 | awidth: QspiWidth::NONE, | ||
| 81 | dwidth: QspiWidth::SING, | ||
| 82 | instruction: CMD_WRITE_SR, | ||
| 83 | address: None, | ||
| 84 | dummy: DummyCycles::_0, | ||
| 85 | }; | ||
| 86 | self.qspi.blocking_write(&buffer, transaction); | ||
| 87 | } | ||
| 88 | |||
| 89 | pub fn read_sr_lsb(&mut self) -> u8 { | ||
| 90 | self.read_register(CMD_READ_SR) | ||
| 91 | } | ||
| 92 | pub fn read_sr_msb(&mut self) -> u8 { | ||
| 93 | self.read_register(CMD_READ_CR) | ||
| 94 | } | ||
| 95 | |||
| 96 | pub fn reset_memory(&mut self) { | ||
| 97 | self.exec_command(CMD_ENABLE_RESET); | ||
| 98 | self.exec_command(CMD_RESET); | ||
| 99 | self.wait_write_finish(); | ||
| 100 | } | ||
| 101 | fn exec_command(&mut self, cmd: u8) { | ||
| 102 | let transaction = TransferConfig { | ||
| 103 | iwidth: QspiWidth::SING, | ||
| 104 | awidth: QspiWidth::NONE, | ||
| 105 | dwidth: QspiWidth::NONE, | ||
| 106 | instruction: cmd, | ||
| 107 | address: None, | ||
| 108 | dummy: DummyCycles::_0, | ||
| 109 | }; | ||
| 110 | self.qspi.blocking_command(transaction); | ||
| 111 | } | ||
| 112 | fn wait_write_finish(&mut self) { | ||
| 113 | while (self.read_sr_lsb() & 0x01) != 0 {} | ||
| 114 | } | ||
| 115 | |||
| 116 | pub fn read_mid(&mut self) -> [u8; 2] { | ||
| 117 | let mut buffer = [0; 2]; | ||
| 118 | let transaction: TransferConfig = TransferConfig { | ||
| 119 | iwidth: QspiWidth::SING, | ||
| 120 | awidth: QspiWidth::SING, | ||
| 121 | dwidth: QspiWidth::SING, | ||
| 122 | instruction: CMD_READ_MID, | ||
| 123 | address: Some(0), | ||
| 124 | dummy: DummyCycles::_0, | ||
| 125 | }; | ||
| 126 | self.qspi.blocking_read(&mut buffer, transaction); | ||
| 127 | buffer | ||
| 128 | } | ||
| 129 | pub fn read_uuid(&mut self) -> [u8; 16] { | ||
| 130 | let mut buffer = [0; 16]; | ||
| 131 | let transaction: TransferConfig = TransferConfig { | ||
| 132 | iwidth: QspiWidth::SING, | ||
| 133 | awidth: QspiWidth::SING, | ||
| 134 | dwidth: QspiWidth::SING, | ||
| 135 | instruction: CMD_READ_UUID, | ||
| 136 | address: Some(0), | ||
| 137 | dummy: DummyCycles::_8, | ||
| 138 | }; | ||
| 139 | self.qspi.blocking_read(&mut buffer, transaction); | ||
| 140 | buffer | ||
| 141 | } | ||
| 142 | pub fn read_id(&mut self) -> [u8; 3] { | ||
| 143 | let mut buffer = [0; 3]; | ||
| 144 | let transaction: TransferConfig = TransferConfig { | ||
| 145 | iwidth: QspiWidth::SING, | ||
| 146 | awidth: QspiWidth::NONE, | ||
| 147 | dwidth: QspiWidth::SING, | ||
| 148 | instruction: CMD_READ_ID, | ||
| 149 | address: None, | ||
| 150 | dummy: DummyCycles::_0, | ||
| 151 | }; | ||
| 152 | self.qspi.blocking_read(&mut buffer, transaction); | ||
| 153 | buffer | ||
| 154 | } | ||
| 155 | |||
| 156 | pub fn enable_mmap(&mut self) { | ||
| 157 | let transaction: TransferConfig = TransferConfig { | ||
| 158 | iwidth: QspiWidth::SING, | ||
| 159 | awidth: QspiWidth::SING, | ||
| 160 | dwidth: QspiWidth::QUAD, | ||
| 161 | instruction: CMD_QUAD_READ, | ||
| 162 | address: Some(0), | ||
| 163 | dummy: DummyCycles::_8, | ||
| 164 | }; | ||
| 165 | self.qspi.enable_memory_map(&transaction); | ||
| 166 | } | ||
| 167 | fn perform_erase(&mut self, addr: u32, cmd: u8) { | ||
| 168 | let transaction = TransferConfig { | ||
| 169 | iwidth: QspiWidth::SING, | ||
| 170 | awidth: QspiWidth::SING, | ||
| 171 | dwidth: QspiWidth::NONE, | ||
| 172 | instruction: cmd, | ||
| 173 | address: Some(addr), | ||
| 174 | dummy: DummyCycles::_0, | ||
| 175 | }; | ||
| 176 | self.enable_write(); | ||
| 177 | self.qspi.blocking_command(transaction); | ||
| 178 | self.wait_write_finish(); | ||
| 179 | } | ||
| 180 | pub fn enable_write(&mut self) { | ||
| 181 | self.exec_command(CMD_WRITE_ENABLE); | ||
| 182 | } | ||
| 183 | pub fn erase_sector(&mut self, addr: u32) { | ||
| 184 | self.perform_erase(addr, CMD_SECTOR_ERASE); | ||
| 185 | } | ||
| 186 | fn write_page(&mut self, addr: u32, buffer: &[u8], len: usize, use_dma: bool) { | ||
| 187 | assert!( | ||
| 188 | (len as u32 + (addr & 0x000000ff)) <= MEMORY_PAGE_SIZE as u32, | ||
| 189 | "write_page(): page write length exceeds page boundary (len = {}, addr = {:X}", | ||
| 190 | len, | ||
| 191 | addr | ||
| 192 | ); | ||
| 193 | |||
| 194 | let transaction = TransferConfig { | ||
| 195 | iwidth: QspiWidth::SING, | ||
| 196 | awidth: QspiWidth::SING, | ||
| 197 | dwidth: QspiWidth::QUAD, | ||
| 198 | instruction: CMD_QUAD_WRITE_PG, | ||
| 199 | address: Some(addr), | ||
| 200 | dummy: DummyCycles::_0, | ||
| 201 | }; | ||
| 202 | self.enable_write(); | ||
| 203 | if use_dma { | ||
| 204 | self.qspi.blocking_write_dma(buffer, transaction); | ||
| 205 | } else { | ||
| 206 | self.qspi.blocking_write(buffer, transaction); | ||
| 207 | } | ||
| 208 | self.wait_write_finish(); | ||
| 209 | } | ||
| 210 | pub fn write_memory(&mut self, addr: u32, buffer: &[u8], use_dma: bool) { | ||
| 211 | let mut left = buffer.len(); | ||
| 212 | let mut place = addr; | ||
| 213 | let mut chunk_start = 0; | ||
| 214 | |||
| 215 | while left > 0 { | ||
| 216 | let max_chunk_size = MEMORY_PAGE_SIZE - (place & 0x000000ff) as usize; | ||
| 217 | let chunk_size = if left >= max_chunk_size { max_chunk_size } else { left }; | ||
| 218 | let chunk = &buffer[chunk_start..(chunk_start + chunk_size)]; | ||
| 219 | self.write_page(place, chunk, chunk_size, use_dma); | ||
| 220 | place += chunk_size as u32; | ||
| 221 | left -= chunk_size; | ||
| 222 | chunk_start += chunk_size; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | pub fn read_memory(&mut self, addr: u32, buffer: &mut [u8], use_dma: bool) { | ||
| 227 | let transaction = TransferConfig { | ||
| 228 | iwidth: QspiWidth::SING, | ||
| 229 | awidth: QspiWidth::SING, | ||
| 230 | dwidth: QspiWidth::QUAD, | ||
| 231 | instruction: CMD_QUAD_READ, | ||
| 232 | address: Some(addr), | ||
| 233 | dummy: DummyCycles::_8, | ||
| 234 | }; | ||
| 235 | if use_dma { | ||
| 236 | self.qspi.blocking_read_dma(buffer, transaction); | ||
| 237 | } else { | ||
| 238 | self.qspi.blocking_read(buffer, transaction); | ||
| 239 | } | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | const MEMORY_ADDR: u32 = 0x00000000 as u32; | ||
| 244 | |||
| 245 | #[embassy_executor::main] | ||
| 246 | async fn main(_spawner: Spawner) { | ||
| 247 | let p = embassy_stm32::init(Default::default()); | ||
| 248 | |||
| 249 | let config = qspi::Config { | ||
| 250 | memory_size: MemorySize::_16MiB, | ||
| 251 | address_size: AddressSize::_24bit, | ||
| 252 | prescaler: 200, | ||
| 253 | cs_high_time: ChipSelectHighTime::_1Cycle, | ||
| 254 | fifo_threshold: FIFOThresholdLevel::_16Bytes, | ||
| 255 | }; | ||
| 256 | let driver = qspi::Qspi::new_bank1(p.QUADSPI, p.PB1, p.PB0, p.PA7, p.PA6, p.PA3, p.PA2, p.DMA2_CH7, config); | ||
| 257 | let mut flash = FlashMemory::new(driver); | ||
| 258 | let mut wr_buf = [0u8; 256]; | ||
| 259 | for i in 0..32 { | ||
| 260 | wr_buf[i] = i as u8; | ||
| 261 | } | ||
| 262 | let mut rd_buf = [0u8; 32]; | ||
| 263 | flash.erase_sector(MEMORY_ADDR); | ||
| 264 | flash.write_memory(MEMORY_ADDR, &wr_buf, false); | ||
| 265 | flash.read_memory(MEMORY_ADDR, &mut rd_buf, false); | ||
| 266 | |||
| 267 | info!("data read from indirect mode: {}", rd_buf); | ||
| 268 | flash.enable_mmap(); | ||
| 269 | let qspi_base = unsafe { core::slice::from_raw_parts(0x9000_0000 as *const u8, 32) }; | ||
| 270 | info!("data read from mmap: {}", qspi_base); | ||
| 271 | loop { | ||
| 272 | Timer::after_millis(1000).await; | ||
| 273 | } | ||
| 274 | } | ||
