aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias <[email protected]>2022-10-26 10:01:52 +0200
committerMathias <[email protected]>2022-10-26 12:24:04 +0200
commit80e58426fcf40b6cea28368e43a7289e827461cf (patch)
tree48ce94c3404b3b95c082914376d5510658a18f38
parentad0eb3f4bd2b124fcb7cda6d6bd88e2b12632ea7 (diff)
Add flash example & flash HIL test
-rwxr-xr-xci.sh2
-rw-r--r--embassy-rp/src/flash.rs39
-rw-r--r--embassy-rp/src/intrinsics.rs1
-rw-r--r--embassy-rp/src/lib.rs2
-rw-r--r--embassy-rp/src/rom_data.rs1
-rw-r--r--examples/rp/Cargo.toml1
-rw-r--r--examples/rp/src/bin/flash.rs84
-rw-r--r--tests/rp/Cargo.toml1
-rw-r--r--tests/rp/src/bin/flash.rs48
9 files changed, 171 insertions, 8 deletions
diff --git a/ci.sh b/ci.sh
index 69440ec36..cd1c0786c 100755
--- a/ci.sh
+++ b/ci.sh
@@ -121,7 +121,7 @@ cargo batch \
121 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi --out-dir out/tests/nucleo-stm32h755zi \ 121 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi --out-dir out/tests/nucleo-stm32h755zi \
122 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55rg --out-dir out/tests/nucleo-stm32wb55rg \ 122 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55rg --out-dir out/tests/nucleo-stm32wb55rg \
123 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32u585ai --out-dir out/tests/iot-stm32u585ai \ 123 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32u585ai --out-dir out/tests/iot-stm32u585ai \
124 --- build --release --manifest-path tests/rp/Cargo.toml --target thumbv6m-none-eabi --features embassy-rp/time-driver --out-dir out/tests/rpi-pico \ 124 --- build --release --manifest-path tests/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/tests/rpi-pico \
125 $BUILD_EXTRA 125 $BUILD_EXTRA
126 126
127 127
diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs
index 7a26085b6..62f68bd3c 100644
--- a/embassy-rp/src/flash.rs
+++ b/embassy-rp/src/flash.rs
@@ -1,8 +1,13 @@
1use core::marker::PhantomData;
2
3use embassy_hal_common::Peripheral;
1use embedded_storage::nor_flash::{ 4use embedded_storage::nor_flash::{
2 check_erase, check_read, check_write, ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind, 5 check_erase, check_read, check_write, ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind,
3 ReadNorFlash, 6 ReadNorFlash,
4}; 7};
5 8
9use crate::peripherals::FLASH;
10
6pub const FLASH_BASE: usize = 0x10000000; 11pub const FLASH_BASE: usize = 0x10000000;
7 12
8// **NOTE**: 13// **NOTE**:
@@ -46,9 +51,13 @@ impl NorFlashError for Error {
46 } 51 }
47} 52}
48 53
49pub struct Flash<const FLASH_SIZE: usize>; 54pub struct Flash<'d, T: Instance, const FLASH_SIZE: usize>(PhantomData<&'d mut T>);
55
56impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> {
57 pub fn new(_flash: impl Peripheral<P = T> + 'd) -> Self {
58 Self(PhantomData)
59 }
50 60
51impl<const FLASH_SIZE: usize> Flash<FLASH_SIZE> {
52 /// Make sure to uphold the contract points with rp2040-flash. 61 /// Make sure to uphold the contract points with rp2040-flash.
53 /// - interrupts must be disabled 62 /// - interrupts must be disabled
54 /// - DMA must not access flash memory 63 /// - DMA must not access flash memory
@@ -81,11 +90,11 @@ impl<const FLASH_SIZE: usize> Flash<FLASH_SIZE> {
81 } 90 }
82} 91}
83 92
84impl<const FLASH_SIZE: usize> ErrorType for Flash<FLASH_SIZE> { 93impl<'d, T: Instance, const FLASH_SIZE: usize> ErrorType for Flash<'d, T, FLASH_SIZE> {
85 type Error = Error; 94 type Error = Error;
86} 95}
87 96
88impl<const FLASH_SIZE: usize> ReadNorFlash for Flash<FLASH_SIZE> { 97impl<'d, T: Instance, const FLASH_SIZE: usize> ReadNorFlash for Flash<'d, T, FLASH_SIZE> {
89 const READ_SIZE: usize = READ_SIZE; 98 const READ_SIZE: usize = READ_SIZE;
90 99
91 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { 100 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
@@ -102,9 +111,9 @@ impl<const FLASH_SIZE: usize> ReadNorFlash for Flash<FLASH_SIZE> {
102 } 111 }
103} 112}
104 113
105impl<const FLASH_SIZE: usize> MultiwriteNorFlash for Flash<FLASH_SIZE> {} 114impl<'d, T: Instance, const FLASH_SIZE: usize> MultiwriteNorFlash for Flash<'d, T, FLASH_SIZE> {}
106 115
107impl<const FLASH_SIZE: usize> NorFlash for Flash<FLASH_SIZE> { 116impl<'d, T: Instance, const FLASH_SIZE: usize> NorFlash for Flash<'d, T, FLASH_SIZE> {
108 const WRITE_SIZE: usize = WRITE_SIZE; 117 const WRITE_SIZE: usize = WRITE_SIZE;
109 118
110 const ERASE_SIZE: usize = ERASE_SIZE; 119 const ERASE_SIZE: usize = ERASE_SIZE;
@@ -112,6 +121,12 @@ impl<const FLASH_SIZE: usize> NorFlash for Flash<FLASH_SIZE> {
112 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { 121 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
113 check_erase(self, from, to)?; 122 check_erase(self, from, to)?;
114 123
124 trace!(
125 "Erasing from 0x{:x} to 0x{:x}",
126 FLASH_BASE as u32 + from,
127 FLASH_BASE as u32 + to
128 );
129
115 let len = to - from; 130 let len = to - from;
116 131
117 unsafe { self.in_ram(|| ram_helpers::flash_range_erase(from, len, true)) }; 132 unsafe { self.in_ram(|| ram_helpers::flash_range_erase(from, len, true)) };
@@ -122,7 +137,7 @@ impl<const FLASH_SIZE: usize> NorFlash for Flash<FLASH_SIZE> {
122 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { 137 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
123 check_write(self, offset, bytes.len())?; 138 check_write(self, offset, bytes.len())?;
124 139
125 trace!("Writing {:?} bytes to 0x{:x}", bytes.len(), offset); 140 trace!("Writing {:?} bytes to 0x{:x}", bytes.len(), FLASH_BASE as u32 + offset);
126 141
127 let end_offset = offset as usize + bytes.len(); 142 let end_offset = offset as usize + bytes.len();
128 143
@@ -351,6 +366,7 @@ mod ram_helpers {
351 rom_data::flash_flush_cache(); 366 rom_data::flash_flush_cache();
352 rom_data::flash_enter_cmd_xip(); 367 rom_data::flash_enter_cmd_xip();
353 */ 368 */
369 #[cfg(target_arch = "arm")]
354 core::arch::asm!( 370 core::arch::asm!(
355 "mov r8, r0", 371 "mov r8, r0",
356 "mov r9, r2", 372 "mov r9, r2",
@@ -402,3 +418,12 @@ mod ram_helpers {
402 ); 418 );
403 } 419 }
404} 420}
421
422mod sealed {
423 pub trait Instance {}
424}
425
426pub trait Instance: sealed::Instance {}
427
428impl sealed::Instance for FLASH {}
429impl Instance for FLASH {}
diff --git a/embassy-rp/src/intrinsics.rs b/embassy-rp/src/intrinsics.rs
index 67e8202a4..3e75fb7fc 100644
--- a/embassy-rp/src/intrinsics.rs
+++ b/embassy-rp/src/intrinsics.rs
@@ -1,4 +1,5 @@
1#![macro_use] 1#![macro_use]
2
2// Credit: taken from `rp-hal` (also licensed Apache+MIT) 3// Credit: taken from `rp-hal` (also licensed Apache+MIT)
3// https://github.com/rp-rs/rp-hal/blob/main/rp2040-hal/src/intrinsics.rs 4// https://github.com/rp-rs/rp-hal/blob/main/rp2040-hal/src/intrinsics.rs
4 5
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index 445639618..f608f1768 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -96,6 +96,8 @@ embassy_hal_common::peripherals! {
96 USB, 96 USB,
97 97
98 RTC, 98 RTC,
99
100 FLASH,
99} 101}
100 102
101#[link_section = ".boot2"] 103#[link_section = ".boot2"]
diff --git a/embassy-rp/src/rom_data.rs b/embassy-rp/src/rom_data.rs
index 8e953dcf2..757a27114 100644
--- a/embassy-rp/src/rom_data.rs
+++ b/embassy-rp/src/rom_data.rs
@@ -7,6 +7,7 @@
7//! > on the device, as well as highly optimized versions of certain key 7//! > on the device, as well as highly optimized versions of certain key
8//! > functionality that would otherwise have to take up space in most user 8//! > functionality that would otherwise have to take up space in most user
9//! > binaries. 9//! > binaries.
10
10// Credit: taken from `rp-hal` (also licensed Apache+MIT) 11// Credit: taken from `rp-hal` (also licensed Apache+MIT)
11// https://github.com/rp-rs/rp-hal/blob/main/rp2040-hal/src/rom_data.rs 12// https://github.com/rp-rs/rp-hal/blob/main/rp2040-hal/src/rom_data.rs
12 13
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index 747dde515..38355bbf8 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -30,6 +30,7 @@ byte-slice-cast = { version = "1.2.0", default-features = false }
30embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" } 30embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" }
31embedded-hal-async = { version = "0.1.0-alpha.1" } 31embedded-hal-async = { version = "0.1.0-alpha.1" }
32embedded-io = { version = "0.3.0", features = ["async", "defmt"] } 32embedded-io = { version = "0.3.0", features = ["async", "defmt"] }
33embedded-storage = { version = "0.3" }
33static_cell = "1.0.0" 34static_cell = "1.0.0"
34 35
35[profile.release] 36[profile.release]
diff --git a/examples/rp/src/bin/flash.rs b/examples/rp/src/bin/flash.rs
new file mode 100644
index 000000000..17549e4be
--- /dev/null
+++ b/examples/rp/src/bin/flash.rs
@@ -0,0 +1,84 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_rp::flash::{ERASE_SIZE, FLASH_BASE};
8use embassy_rp::peripherals::FLASH;
9use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
10use {defmt_rtt as _, panic_probe as _};
11
12const ADDR_OFFSET: u32 = 0x100000;
13const FLASH_SIZE: usize = 2 * 1024 * 1024;
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) {
17 let p = embassy_rp::init(Default::default());
18 info!("Hello World!");
19
20 let mut flash = embassy_rp::flash::Flash::<_, FLASH_SIZE>::new(p.FLASH);
21
22 erase_write_sector(&mut flash, 0x00);
23
24 multiwrite_bytes(&mut flash, ERASE_SIZE as u32);
25
26 loop {}
27}
28
29fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE>, offset: u32) {
30 info!(">>>> [multiwrite_bytes]");
31 let mut read_buf = [0u8; ERASE_SIZE];
32 defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut read_buf));
33
34 info!("Addr of flash block is {:x}", ADDR_OFFSET + offset + FLASH_BASE as u32);
35 info!("Contents start with {=[u8]}", read_buf[0..4]);
36
37 defmt::unwrap!(flash.erase(ADDR_OFFSET + offset, ADDR_OFFSET + offset + ERASE_SIZE as u32));
38
39 defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut read_buf));
40 info!("Contents after erase starts with {=[u8]}", read_buf[0..4]);
41 if read_buf.iter().any(|x| *x != 0xFF) {
42 defmt::panic!("unexpected");
43 }
44
45 defmt::unwrap!(flash.write(ADDR_OFFSET + offset, &[0x01]));
46 defmt::unwrap!(flash.write(ADDR_OFFSET + offset + 1, &[0x02]));
47 defmt::unwrap!(flash.write(ADDR_OFFSET + offset + 2, &[0x03]));
48 defmt::unwrap!(flash.write(ADDR_OFFSET + offset + 3, &[0x04]));
49
50 defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut read_buf));
51 info!("Contents after write starts with {=[u8]}", read_buf[0..4]);
52 if &read_buf[0..4] != &[0x01, 0x02, 0x03, 0x04] {
53 defmt::panic!("unexpected");
54 }
55}
56
57fn erase_write_sector(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE>, offset: u32) {
58 info!(">>>> [erase_write_sector]");
59 let mut buf = [0u8; ERASE_SIZE];
60 defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut buf));
61
62 info!("Addr of flash block is {:x}", ADDR_OFFSET + offset + FLASH_BASE as u32);
63 info!("Contents start with {=[u8]}", buf[0..4]);
64
65 defmt::unwrap!(flash.erase(ADDR_OFFSET + offset, ADDR_OFFSET + offset + ERASE_SIZE as u32));
66
67 defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut buf));
68 info!("Contents after erase starts with {=[u8]}", buf[0..4]);
69 if buf.iter().any(|x| *x != 0xFF) {
70 defmt::panic!("unexpected");
71 }
72
73 for b in buf.iter_mut() {
74 *b = 0xDA;
75 }
76
77 defmt::unwrap!(flash.write(ADDR_OFFSET + offset, &buf));
78
79 defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut buf));
80 info!("Contents after write starts with {=[u8]}", buf[0..4]);
81 if buf.iter().any(|x| *x != 0xDA) {
82 defmt::panic!("unexpected");
83 }
84}
diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml
index d6770d6e9..48c88e85b 100644
--- a/tests/rp/Cargo.toml
+++ b/tests/rp/Cargo.toml
@@ -22,6 +22,7 @@ embedded-hal-async = { version = "=0.1.0-alpha.2" }
22panic-probe = { version = "0.3.0", features = ["print-defmt"] } 22panic-probe = { version = "0.3.0", features = ["print-defmt"] }
23futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 23futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
24embedded-io = { version = "0.3.0", features = ["async"] } 24embedded-io = { version = "0.3.0", features = ["async"] }
25embedded-storage = { version = "0.3" }
25 26
26[profile.dev] 27[profile.dev]
27debug = 2 28debug = 2
diff --git a/tests/rp/src/bin/flash.rs b/tests/rp/src/bin/flash.rs
new file mode 100644
index 000000000..4cbd78fe9
--- /dev/null
+++ b/tests/rp/src/bin/flash.rs
@@ -0,0 +1,48 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_rp::flash::{ERASE_SIZE, FLASH_BASE};
8use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
9use {defmt_rtt as _, panic_probe as _};
10
11const ADDR_OFFSET: u32 = 0x4000;
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) {
15 let p = embassy_rp::init(Default::default());
16 info!("Hello World!");
17
18 let mut flash = embassy_rp::flash::Flash::<_, { 2 * 1024 * 1024 }>::new(p.FLASH);
19
20 let mut buf = [0u8; ERASE_SIZE];
21 defmt::unwrap!(flash.read(ADDR_OFFSET, &mut buf));
22
23 info!("Addr of flash block is {:x}", ADDR_OFFSET + FLASH_BASE as u32);
24 info!("Contents start with {=[u8]}", buf[0..4]);
25
26 defmt::unwrap!(flash.erase(ADDR_OFFSET, ADDR_OFFSET + ERASE_SIZE as u32));
27
28 defmt::unwrap!(flash.read(ADDR_OFFSET, &mut buf));
29 info!("Contents after erase starts with {=[u8]}", buf[0..4]);
30 if buf.iter().any(|x| *x != 0xFF) {
31 defmt::panic!("unexpected");
32 }
33
34 for b in buf.iter_mut() {
35 *b = 0xDA;
36 }
37
38 defmt::unwrap!(flash.write(ADDR_OFFSET, &mut buf));
39
40 defmt::unwrap!(flash.read(ADDR_OFFSET, &mut buf));
41 info!("Contents after write starts with {=[u8]}", buf[0..4]);
42 if buf.iter().any(|x| *x != 0xDA) {
43 defmt::panic!("unexpected");
44 }
45
46 info!("Test OK");
47 cortex_m::asm::bkpt();
48}