Skip to content

Commit 7a0be8a

Browse files
bors[bot]huntc
andauthored
Merge #337
337: Provides common Nvmc functionality r=jonas-schievink a=huntc The [embedded-storage](https://github.com/rust-embedded-community/embedded-storage) traits are implemented to provide a higher-level abstraction for reading and writing from/to flash storage. In the first instance, support is provided for the nRF52 boards and the nRF9160, but other boards should be relatively easy to support if required in the future. Sample usage of writing to flash given some 32 bit aligned slice of bytes: ```rust // Erase a page let _ = nvmc.try_erase(0, 4096); // Write the 32 bit aligned slice let _ = nvmc.try_write(0, some_u8_slice_on_32_bit_bounds); ``` An example of establishing the `Nvmc` on the nRF9160: ```rust let mut nvmc = Nvmc::new(board.NVMC_NS, unsafe { &mut CONFIG }); ``` ...where CONFIG points to flash: ```rust extern "C" { #[link_name = "_config"] static mut CONFIG: [u32; 1024]; } ``` ...which can be expressed in a memory layout: ``` MEMORY { /* NOTE 1 K = 1 KiBi = 1024 bytes */ FLASH : ORIGIN = 0x00040000, LENGTH = 764K CONFIG : ORIGIN = ORIGIN(FLASH) + LENGTH(FLASH), LENGTH = 4K /* 4K is the flash page size */ RAM : ORIGIN = 0x20020000, LENGTH = 128K } _config = ORIGIN(CONFIG); ``` Testing on the nRF52840 device can be achieved via `cargo test --test nvmc` from within the `nrf52840-hal-tests` folder. Fixes #336 TODO: * [x] Implement the `ReadNorFlash` methods * [x] Implement the `NorFlash` methods * [x] Provide an `Instance` for the nRF52840 * [x] Provide an `Instance` for the nRF9160 * [x] Provide a nvmc module in nrf52840-tests for the new abstraction * [x] Write some more tests to test some boundary conditions * [x] Go through the code finely and compare it again with the nrfx library * [x] Provide an example of reading, writing and erasing from/to storage Co-authored-by: huntc <[email protected]>
2 parents 70ad87a + b005d57 commit 7a0be8a

File tree

15 files changed

+588
-2
lines changed

15 files changed

+588
-2
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/target/
1+
target/
22
.gdb_history
33
[._]*.sw[a-p]
44
**/*.rs.bk

examples/nvmc-demo/Cargo.toml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[package]
2+
name = "nvmc-demo"
3+
version = "0.1.0"
4+
authors = ["Christopher Hunt"]
5+
edition = "2018"
6+
publish = false
7+
8+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
9+
10+
[dependencies]
11+
cortex-m = "0.6.2"
12+
cortex-m-rt = "0.6.12"
13+
embedded-storage = "0.1.0"
14+
rtt-target = {version = "0.2.0", features = ["cortex-m"] }
15+
16+
[dependencies.embedded-hal]
17+
version = "0.2.3"
18+
features = ["unproven"]
19+
20+
[dependencies.nrf52840-hal]
21+
features = ["rt"]
22+
path = "../../nrf52840-hal"
23+
optional = true
24+
25+
[features]
26+
52840 = ["nrf52840-hal"]

examples/nvmc-demo/Embed.toml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
[default.probe]
2+
# USB vendor ID
3+
# usb_vid = "1337"
4+
# USB product ID
5+
# usb_pid = "1337"
6+
# Serial number
7+
# serial = "12345678"
8+
# The protocol to be used for communicating with the target.
9+
protocol = "Swd"
10+
# The speed in kHz of the data link to the target.
11+
# speed = 1337
12+
13+
[default.flashing]
14+
# Whether or not the target should be flashed.
15+
enabled = true
16+
# Whether or not the target should be halted after reset.
17+
# DEPRECATED, moved to reset section
18+
halt_afterwards = false
19+
# Whether or not bytes erased but not rewritten with data from the ELF
20+
# should be restored with their contents before erasing.
21+
restore_unwritten_bytes = false
22+
# The path where an SVG of the assembled flash layout should be written to.
23+
# flash_layout_output_path = "out.svg"
24+
25+
[default.reset]
26+
# Whether or not the target should be reset.
27+
# When flashing is enabled as well, the target will be reset after flashing.
28+
enabled = true
29+
# Whether or not the target should be halted after reset.
30+
halt_afterwards = false
31+
32+
[default.general]
33+
# The chip name of the chip to be debugged.
34+
chip = "nRF52840_xxAA"
35+
# A list of chip descriptions to be loaded during runtime.
36+
chip_descriptions = []
37+
# The default log level to be used. Possible values are one of:
38+
# "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"
39+
log_level = "WARN"
40+
41+
[default.rtt]
42+
# Whether or not an RTTUI should be opened after flashing.
43+
# This is exclusive and cannot be used with GDB at the moment.
44+
enabled = true
45+
# A list of channel associations to be displayed. If left empty, all channels are displayed.
46+
channels = [
47+
# { up = 0, down = 0, name = "name", format = "String" }
48+
]
49+
# The duration in ms for which the logger should retry to attach to RTT.
50+
timeout = 3000
51+
# Whether timestamps in the RTTUI are enabled
52+
show_timestamps = true
53+
# Whether to save rtt history buffer on exit.
54+
log_enabled = false
55+
# Where to save rtt history buffer relative to manifest path.
56+
log_path = "./logs"
57+
58+
[default.gdb]
59+
# Whether or not a GDB server should be opened after flashing.
60+
# This is exclusive and cannot be used with RTT at the moment.
61+
enabled = false
62+
# The connection string in host:port format wher the GDB server will open a socket.
63+
# gdb_connection_string

examples/nvmc-demo/build.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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+
11+
use std::env;
12+
use std::fs::File;
13+
use std::io::Write;
14+
use std::path::PathBuf;
15+
16+
fn 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+
}

examples/nvmc-demo/memory.x

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
MEMORY
2+
{
3+
/* NOTE 1 K = 1 KiBi = 1024 bytes */
4+
FLASH : ORIGIN = 0x00000000, LENGTH = 1020K
5+
CONFIG : ORIGIN = ORIGIN(FLASH) + LENGTH(FLASH), LENGTH = 4K /* 4K is the flash page size */
6+
RAM : ORIGIN = 0x20000000, LENGTH = 256K
7+
}
8+
9+
_config = ORIGIN(CONFIG);
10+
11+
/* This is where the call stack will be allocated. */
12+
/* The stack is of the full descending type. */
13+
/* You may want to use this variable to locate the call stack and static
14+
variables in different memory regions. Below is shown the default value */
15+
/* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */
16+
17+
/* You can use this symbol to customize the location of the .text section */
18+
/* If omitted the .text section will be placed right after the .vector_table
19+
section */
20+
/* This is required only on microcontrollers that store some configuration right
21+
after the vector table */
22+
/* _stext = ORIGIN(FLASH) + 0x400; */
23+
24+
/* Example of putting non-initialized variables into custom RAM locations. */
25+
/* This assumes you have defined a region RAM2 above, and in the Rust
26+
sources added the attribute `#[link_section = ".ram2bss"]` to the data
27+
you want to place there. */
28+
/* Note that the section will not be zero-initialized by the runtime! */
29+
/* SECTIONS {
30+
.ram2bss (NOLOAD) : ALIGN(4) {
31+
*(.ram2bss);
32+
. = ALIGN(4);
33+
} > RAM2
34+
} INSERT AFTER .bss;
35+
*/

examples/nvmc-demo/src/main.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
// Simple NVMC example
5+
6+
#[cfg(feature = "52840")]
7+
use nrf52840_hal as hal;
8+
9+
use embedded_storage::nor_flash::NorFlash;
10+
use embedded_storage::nor_flash::ReadNorFlash;
11+
use hal::nvmc::Nvmc;
12+
use rtt_target::{rprintln, rtt_init_print};
13+
14+
const CONFIG_SIZE: usize = 1024;
15+
extern "C" {
16+
#[link_name = "_config"]
17+
static mut CONFIG: [u32; CONFIG_SIZE];
18+
}
19+
20+
// To run this: `cargo embed --features "52840" --target thumbv7em-none-eabihf`
21+
22+
#[cortex_m_rt::entry]
23+
fn main() -> ! {
24+
rtt_init_print!();
25+
26+
let p = hal::pac::Peripherals::take().unwrap();
27+
28+
#[cfg(feature = "52840")]
29+
let mut nvmc = Nvmc::new(p.NVMC, unsafe { &mut CONFIG });
30+
31+
assert!(nvmc.try_erase(0, CONFIG_SIZE as u32 * 4).is_ok());
32+
let write_buf: [u8; 4] = [1, 2, 3, 4];
33+
assert!(nvmc.try_write(0, &write_buf).is_ok());
34+
let mut read_buf = [0u8; 2];
35+
assert!(nvmc.try_read(0, &mut read_buf).is_ok());
36+
assert_eq!(read_buf, write_buf[0..2]);
37+
38+
rprintln!("What was written to flash was read!");
39+
40+
loop {
41+
cortex_m::asm::wfe();
42+
}
43+
}
44+
45+
#[panic_handler] // panicking behavior
46+
fn panic(_: &core::panic::PanicInfo) -> ! {
47+
loop {
48+
cortex_m::asm::bkpt();
49+
}
50+
}

nrf-hal-common/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ fixed = "1.0.0"
2626
rand_core = "0.6.3"
2727
cfg-if = "1.0.0"
2828
embedded-dma = "0.1.1"
29+
embedded-storage = "0.1.0"
2930

3031
[dependencies.void]
3132
default-features = false

nrf-hal-common/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ pub mod i2s;
4747
pub mod ieee802154;
4848
#[cfg(not(any(feature = "52811", feature = "52810", feature = "9160")))]
4949
pub mod lpcomp;
50+
#[cfg(not(feature = "51"))]
51+
pub mod nvmc;
5052
#[cfg(not(feature = "9160"))]
5153
pub mod ppi;
5254
#[cfg(not(feature = "51"))]

0 commit comments

Comments
 (0)