aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-10-23 08:28:25 +0000
committerGitHub <[email protected]>2021-10-23 08:28:25 +0000
commitf3f3858328ed4f13efb3790e32ee4fba772b57a2 (patch)
tree2efed3b61dbd91881ba5227c2887316adb97241d
parenta8797f84f69b7668a3f89b6cba3e39bce5649079 (diff)
parente78d226acd5e2dc5f2eecfc98269747daf7e0633 (diff)
Merge #444
444: nrf: add NVMC driver. r=lulf a=Dirbaio I haven't implemented `embassy_traits::Flash` because I want to change it to match embedded_storage, which is much better designed. Either way, NVMC can't do async anyway, so the best we could do is implementing the async trait in a blocking way... Co-authored-by: Dario Nieuwenhuis <[email protected]>
-rw-r--r--embassy-nrf/Cargo.toml1
-rw-r--r--embassy-nrf/src/chips/nrf52805.rs5
-rw-r--r--embassy-nrf/src/chips/nrf52810.rs5
-rw-r--r--embassy-nrf/src/chips/nrf52811.rs5
-rw-r--r--embassy-nrf/src/chips/nrf52820.rs5
-rw-r--r--embassy-nrf/src/chips/nrf52832.rs9
-rw-r--r--embassy-nrf/src/chips/nrf52833.rs5
-rw-r--r--embassy-nrf/src/chips/nrf52840.rs5
-rw-r--r--embassy-nrf/src/lib.rs2
-rw-r--r--embassy-nrf/src/nvmc.rs123
-rw-r--r--examples/nrf/Cargo.toml1
-rw-r--r--examples/nrf/src/bin/nvmc.rs44
12 files changed, 210 insertions, 0 deletions
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml
index d4d4ab8d8..fc1ec6b01 100644
--- a/embassy-nrf/Cargo.toml
+++ b/embassy-nrf/Cargo.toml
@@ -49,6 +49,7 @@ futures = { version = "0.3.17", default-features = false }
49critical-section = "0.2.3" 49critical-section = "0.2.3"
50rand_core = "0.6.3" 50rand_core = "0.6.3"
51fixed = "1.10.0" 51fixed = "1.10.0"
52embedded-storage = "0.2.0"
52 53
53nrf52805-pac = { version = "0.10.1", optional = true, features = [ "rt" ] } 54nrf52805-pac = { version = "0.10.1", optional = true, features = [ "rt" ] }
54nrf52810-pac = { version = "0.10.1", optional = true, features = [ "rt" ] } 55nrf52810-pac = { version = "0.10.1", optional = true, features = [ "rt" ] }
diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs
index 317e6ed66..d68697936 100644
--- a/embassy-nrf/src/chips/nrf52805.rs
+++ b/embassy-nrf/src/chips/nrf52805.rs
@@ -4,6 +4,8 @@ pub use nrf52805_pac as pac;
4pub const EASY_DMA_SIZE: usize = (1 << 14) - 1; 4pub const EASY_DMA_SIZE: usize = (1 << 14) - 1;
5pub const FORCE_COPY_BUFFER_SIZE: usize = 256; 5pub const FORCE_COPY_BUFFER_SIZE: usize = 256;
6 6
7pub const FLASH_SIZE: usize = 192 * 1024;
8
7embassy_hal_common::peripherals! { 9embassy_hal_common::peripherals! {
8 // RTC 10 // RTC
9 RTC0, 11 RTC0,
@@ -12,6 +14,9 @@ embassy_hal_common::peripherals! {
12 // WDT 14 // WDT
13 WDT, 15 WDT,
14 16
17 // NVMC
18 NVMC,
19
15 // RNG 20 // RNG
16 RNG, 21 RNG,
17 22
diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs
index b26f30cbf..c119e7cdb 100644
--- a/embassy-nrf/src/chips/nrf52810.rs
+++ b/embassy-nrf/src/chips/nrf52810.rs
@@ -4,6 +4,8 @@ pub use nrf52810_pac as pac;
4pub const EASY_DMA_SIZE: usize = (1 << 10) - 1; 4pub const EASY_DMA_SIZE: usize = (1 << 10) - 1;
5pub const FORCE_COPY_BUFFER_SIZE: usize = 256; 5pub const FORCE_COPY_BUFFER_SIZE: usize = 256;
6 6
7pub const FLASH_SIZE: usize = 192 * 1024;
8
7embassy_hal_common::peripherals! { 9embassy_hal_common::peripherals! {
8 // RTC 10 // RTC
9 RTC0, 11 RTC0,
@@ -12,6 +14,9 @@ embassy_hal_common::peripherals! {
12 // WDT 14 // WDT
13 WDT, 15 WDT,
14 16
17 // NVMC
18 NVMC,
19
15 // RNG 20 // RNG
16 RNG, 21 RNG,
17 22
diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs
index 9fbe3594e..3c9df40fe 100644
--- a/embassy-nrf/src/chips/nrf52811.rs
+++ b/embassy-nrf/src/chips/nrf52811.rs
@@ -4,6 +4,8 @@ pub use nrf52811_pac as pac;
4pub const EASY_DMA_SIZE: usize = (1 << 14) - 1; 4pub const EASY_DMA_SIZE: usize = (1 << 14) - 1;
5pub const FORCE_COPY_BUFFER_SIZE: usize = 256; 5pub const FORCE_COPY_BUFFER_SIZE: usize = 256;
6 6
7pub const FLASH_SIZE: usize = 192 * 1024;
8
7embassy_hal_common::peripherals! { 9embassy_hal_common::peripherals! {
8 // RTC 10 // RTC
9 RTC0, 11 RTC0,
@@ -12,6 +14,9 @@ embassy_hal_common::peripherals! {
12 // WDT 14 // WDT
13 WDT, 15 WDT,
14 16
17 // NVMC
18 NVMC,
19
15 // RNG 20 // RNG
16 RNG, 21 RNG,
17 22
diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs
index abbdba7ac..8a8e23a9e 100644
--- a/embassy-nrf/src/chips/nrf52820.rs
+++ b/embassy-nrf/src/chips/nrf52820.rs
@@ -4,6 +4,8 @@ pub use nrf52820_pac as pac;
4pub const EASY_DMA_SIZE: usize = (1 << 15) - 1; 4pub const EASY_DMA_SIZE: usize = (1 << 15) - 1;
5pub const FORCE_COPY_BUFFER_SIZE: usize = 512; 5pub const FORCE_COPY_BUFFER_SIZE: usize = 512;
6 6
7pub const FLASH_SIZE: usize = 256 * 1024;
8
7embassy_hal_common::peripherals! { 9embassy_hal_common::peripherals! {
8 // RTC 10 // RTC
9 RTC0, 11 RTC0,
@@ -12,6 +14,9 @@ embassy_hal_common::peripherals! {
12 // WDT 14 // WDT
13 WDT, 15 WDT,
14 16
17 // NVMC
18 NVMC,
19
15 // RNG 20 // RNG
16 RNG, 21 RNG,
17 22
diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs
index de6dd7a8c..c1b02a0bf 100644
--- a/embassy-nrf/src/chips/nrf52832.rs
+++ b/embassy-nrf/src/chips/nrf52832.rs
@@ -4,6 +4,12 @@ pub use nrf52832_pac as pac;
4pub const EASY_DMA_SIZE: usize = (1 << 8) - 1; 4pub const EASY_DMA_SIZE: usize = (1 << 8) - 1;
5pub const FORCE_COPY_BUFFER_SIZE: usize = 255; 5pub const FORCE_COPY_BUFFER_SIZE: usize = 255;
6 6
7// There are two variants. We set the higher size to make the entire flash
8// usable in xxAA, but we'll probably split this in two cargi features later.
9// nrf52832xxAA = 512kb
10// nrf52832xxAB = 256kb
11pub const FLASH_SIZE: usize = 512 * 1024;
12
7embassy_hal_common::peripherals! { 13embassy_hal_common::peripherals! {
8 // RTC 14 // RTC
9 RTC0, 15 RTC0,
@@ -13,6 +19,9 @@ embassy_hal_common::peripherals! {
13 // WDT 19 // WDT
14 WDT, 20 WDT,
15 21
22 // NVMC
23 NVMC,
24
16 // RNG 25 // RNG
17 RNG, 26 RNG,
18 27
diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs
index c5e1c9d33..4f5c26002 100644
--- a/embassy-nrf/src/chips/nrf52833.rs
+++ b/embassy-nrf/src/chips/nrf52833.rs
@@ -4,6 +4,8 @@ pub use nrf52833_pac as pac;
4pub const EASY_DMA_SIZE: usize = (1 << 16) - 1; 4pub const EASY_DMA_SIZE: usize = (1 << 16) - 1;
5pub const FORCE_COPY_BUFFER_SIZE: usize = 512; 5pub const FORCE_COPY_BUFFER_SIZE: usize = 512;
6 6
7pub const FLASH_SIZE: usize = 512 * 1024;
8
7embassy_hal_common::peripherals! { 9embassy_hal_common::peripherals! {
8 // RTC 10 // RTC
9 RTC0, 11 RTC0,
@@ -13,6 +15,9 @@ embassy_hal_common::peripherals! {
13 // WDT 15 // WDT
14 WDT, 16 WDT,
15 17
18 // NVMC
19 NVMC,
20
16 // RNG 21 // RNG
17 RNG, 22 RNG,
18 23
diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs
index 76cabe6f1..1006acd95 100644
--- a/embassy-nrf/src/chips/nrf52840.rs
+++ b/embassy-nrf/src/chips/nrf52840.rs
@@ -4,6 +4,8 @@ pub use nrf52840_pac as pac;
4pub const EASY_DMA_SIZE: usize = (1 << 16) - 1; 4pub const EASY_DMA_SIZE: usize = (1 << 16) - 1;
5pub const FORCE_COPY_BUFFER_SIZE: usize = 512; 5pub const FORCE_COPY_BUFFER_SIZE: usize = 512;
6 6
7pub const FLASH_SIZE: usize = 1024 * 1024;
8
7embassy_hal_common::peripherals! { 9embassy_hal_common::peripherals! {
8 // RTC 10 // RTC
9 RTC0, 11 RTC0,
@@ -13,6 +15,9 @@ embassy_hal_common::peripherals! {
13 // WDT 15 // WDT
14 WDT, 16 WDT,
15 17
18 // NVMC
19 NVMC,
20
16 // RNG 21 // RNG
17 RNG, 22 RNG,
18 23
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 961a97ce9..c21c4d398 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -29,6 +29,8 @@ pub mod buffered_uarte;
29pub mod gpio; 29pub mod gpio;
30#[cfg(feature = "gpiote")] 30#[cfg(feature = "gpiote")]
31pub mod gpiote; 31pub mod gpiote;
32#[cfg(not(feature = "nrf9160"))]
33pub mod nvmc;
32pub mod ppi; 34pub mod ppi;
33#[cfg(not(any(feature = "nrf52805", feature = "nrf52820")))] 35#[cfg(not(any(feature = "nrf52805", feature = "nrf52820")))]
34pub mod pwm; 36pub mod pwm;
diff --git a/embassy-nrf/src/nvmc.rs b/embassy-nrf/src/nvmc.rs
new file mode 100644
index 000000000..312e1d5a6
--- /dev/null
+++ b/embassy-nrf/src/nvmc.rs
@@ -0,0 +1,123 @@
1//! Nvmcerature sensor interface.
2
3use crate::pac;
4use crate::peripherals::NVMC;
5
6use core::marker::PhantomData;
7use core::ptr;
8use core::slice;
9use embassy::util::Unborrow;
10use embassy_hal_common::unborrow;
11use embedded_storage::nor_flash::{MultiwriteNorFlash, NorFlash, ReadNorFlash};
12
13const PAGE_SIZE: usize = 4096;
14const FLASH_SIZE: usize = crate::chip::FLASH_SIZE;
15
16#[derive(Debug, Copy, Clone, PartialEq, Eq)]
17#[cfg_attr(feature = "defmt", derive(defmt::Format))]
18pub enum Error {
19 OutOfBounds,
20 Unaligned,
21}
22
23pub struct Nvmc<'d> {
24 _p: PhantomData<&'d NVMC>,
25}
26
27impl<'d> Nvmc<'d> {
28 pub fn new(_p: impl Unborrow<Target = NVMC> + 'd) -> Self {
29 unborrow!(_p);
30
31 Self { _p: PhantomData }
32 }
33
34 fn regs() -> &'static pac::nvmc::RegisterBlock {
35 unsafe { &*pac::NVMC::ptr() }
36 }
37
38 fn wait_ready(&mut self) {
39 let p = Self::regs();
40 while p.ready.read().ready().is_busy() {}
41 }
42}
43
44impl<'d> MultiwriteNorFlash for Nvmc<'d> {}
45
46impl<'d> ReadNorFlash for Nvmc<'d> {
47 type Error = Error;
48
49 const READ_SIZE: usize = 1;
50
51 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
52 if offset as usize >= FLASH_SIZE || offset as usize + bytes.len() > FLASH_SIZE {
53 return Err(Error::OutOfBounds);
54 }
55
56 let flash_data = unsafe { slice::from_raw_parts(offset as *const u8, bytes.len()) };
57 bytes.copy_from_slice(flash_data);
58 Ok(())
59 }
60
61 fn capacity(&self) -> usize {
62 FLASH_SIZE
63 }
64}
65
66impl<'d> NorFlash for Nvmc<'d> {
67 const WRITE_SIZE: usize = 4;
68 const ERASE_SIZE: usize = PAGE_SIZE;
69
70 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
71 if to < from || to as usize > FLASH_SIZE {
72 return Err(Error::OutOfBounds);
73 }
74 if from as usize % PAGE_SIZE != 0 || to as usize % PAGE_SIZE != 0 {
75 return Err(Error::Unaligned);
76 }
77
78 let p = Self::regs();
79
80 p.config.write(|w| w.wen().een());
81 self.wait_ready();
82
83 for page in (from..to).step_by(PAGE_SIZE) {
84 p.erasepage().write(|w| unsafe { w.bits(page) });
85 self.wait_ready();
86 }
87
88 p.config.reset();
89 self.wait_ready();
90
91 Ok(())
92 }
93
94 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
95 if offset as usize + bytes.len() > FLASH_SIZE {
96 return Err(Error::OutOfBounds);
97 }
98 if offset as usize % 4 != 0 || bytes.len() as usize % 4 != 0 {
99 return Err(Error::Unaligned);
100 }
101
102 let p = Self::regs();
103
104 p.config.write(|w| w.wen().wen());
105 self.wait_ready();
106
107 unsafe {
108 let p_src = bytes.as_ptr() as *const u32;
109 let p_dst = offset as *mut u32;
110 let words = bytes.len() / 4;
111 for i in 0..words {
112 let w = ptr::read_unaligned(p_src.add(i));
113 ptr::write_volatile(p_dst.add(i), w);
114 self.wait_ready();
115 }
116 }
117
118 p.config.reset();
119 self.wait_ready();
120
121 Ok(())
122 }
123}
diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml
index b71dfa0d4..b89aa513f 100644
--- a/examples/nrf/Cargo.toml
+++ b/examples/nrf/Cargo.toml
@@ -30,3 +30,4 @@ embedded-hal = "0.2.6"
30panic-probe = { version = "0.2.0", features = ["print-defmt"] } 30panic-probe = { version = "0.2.0", features = ["print-defmt"] }
31futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 31futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
32rand = { version = "0.8.4", default-features = false } 32rand = { version = "0.8.4", default-features = false }
33embedded-storage = "0.2.0"
diff --git a/examples/nrf/src/bin/nvmc.rs b/examples/nrf/src/bin/nvmc.rs
new file mode 100644
index 000000000..f36895636
--- /dev/null
+++ b/examples/nrf/src/bin/nvmc.rs
@@ -0,0 +1,44 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5#[path = "../example_common.rs"]
6mod example_common;
7use embassy::executor::Spawner;
8use embassy::time::{Duration, Timer};
9use embassy_nrf::nvmc::Nvmc;
10use embassy_nrf::Peripherals;
11use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
12use example_common::*;
13
14#[embassy::main]
15async fn main(_spawner: Spawner, p: Peripherals) {
16 info!("Hello NVMC!");
17
18 // probe-run breaks without this, I'm not sure why.
19 Timer::after(Duration::from_secs(1)).await;
20
21 let mut f = Nvmc::new(p.NVMC);
22 const ADDR: u32 = 0x80000;
23
24 info!("Reading...");
25 let mut buf = [0u8; 4];
26 unwrap!(f.read(ADDR, &mut buf));
27 info!("Read: {=[u8]:x}", buf);
28
29 info!("Erasing...");
30 unwrap!(f.erase(ADDR, ADDR + 4096));
31
32 info!("Reading...");
33 let mut buf = [0u8; 4];
34 unwrap!(f.read(ADDR, &mut buf));
35 info!("Read: {=[u8]:x}", buf);
36
37 info!("Writing...");
38 unwrap!(f.write(ADDR, &[1, 2, 3, 4]));
39
40 info!("Reading...");
41 let mut buf = [0u8; 4];
42 unwrap!(f.read(ADDR, &mut buf));
43 info!("Read: {=[u8]:x}", buf);
44}