From 3a6b57c90b8ee8bcb52d3cace0578a0c390ab85a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6rtsell?= Date: Thu, 25 Aug 2022 10:29:01 +0200 Subject: [PATCH 1/8] Add Flash Sector Tokens and read_word Funcitonality (WIP) Add Erase Sector Method Add Write Page Method Add Write Word Method Add Two Bootloader Examples --- boards/atsamv71_xult/Cargo.lock | 8 + boards/atsamv71_xult/Cargo.toml | 2 + boards/atsamv71_xult/examples/blinky.rs | 27 +- boards/atsamv71_xult/examples/blinky_irq.rs | 2 +- boards/atsamv71_xult/examples/bootloader.rs | 172 ++++++++++++ boards/atsamv71_xult/examples/efc.rs | 63 +++++ .../examples/minimal-bootloader.rs | 15 ++ hal/src/efc.rs | 249 +++++++++++++++++- 8 files changed, 523 insertions(+), 15 deletions(-) create mode 100644 boards/atsamv71_xult/examples/bootloader.rs create mode 100644 boards/atsamv71_xult/examples/efc.rs create mode 100644 boards/atsamv71_xult/examples/minimal-bootloader.rs diff --git a/boards/atsamv71_xult/Cargo.lock b/boards/atsamv71_xult/Cargo.lock index 48971694..6c0d51a5 100644 --- a/boards/atsamv71_xult/Cargo.lock +++ b/boards/atsamv71_xult/Cargo.lock @@ -26,10 +26,12 @@ version = "0.4.2" dependencies = [ "atsamx7x-hal", "cortex-m", + "cortex-m-rt", "cortex-m-rtic", "dwt-systick-monotonic", "heapless", "mcan", + "panic-halt", "panic-rtt-target", "rtt-target", "typenum", @@ -357,6 +359,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" +[[package]] +name = "panic-halt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812" + [[package]] name = "panic-rtt-target" version = "0.1.2" diff --git a/boards/atsamv71_xult/Cargo.toml b/boards/atsamv71_xult/Cargo.toml index 5bc456ea..122ab190 100644 --- a/boards/atsamv71_xult/Cargo.toml +++ b/boards/atsamv71_xult/Cargo.toml @@ -10,7 +10,9 @@ license = "MIT OR Apache-2.0" [dependencies] cortex-m-rtic = "1.0" cortex-m = "0.7" +cortex-m-rt = "*" panic-rtt-target = { version = "0.1.2", features = ["cortex-m"] } +panic-halt = "*" rtt-target = { version = "0.3.1", features = ["cortex-m"] } heapless = "0.7" usbd-serial = "0.1.1" diff --git a/boards/atsamv71_xult/examples/blinky.rs b/boards/atsamv71_xult/examples/blinky.rs index c98e55ff..f8f2c9e0 100644 --- a/boards/atsamv71_xult/examples/blinky.rs +++ b/boards/atsamv71_xult/examples/blinky.rs @@ -3,19 +3,19 @@ #![no_main] use panic_rtt_target as _; - +// use panic_halt as _; #[rtic::app(device = hal::pac, peripherals = true, dispatchers = [UART0])] mod app { use atsamx7x_hal as hal; use hal::clocks::*; - use hal::efc::*; + use hal::efc::{Efc, VddioLevel}; use hal::ehal::digital::v2::ToggleableOutputPin; use hal::pio::*; use hal::rtt::*; use rtt_target::{rprintln, rtt_init_print}; - #[monotonic(binds = RTT, default = true)] - type MyMono = Mono<8192>; + // #[monotonic(binds = RTT, default = true)] + // type MyMono = Mono<8192>; #[shared] struct Shared {} @@ -28,6 +28,7 @@ mod app { #[init] fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) { rtt_init_print!(); + rprintln!("Init"); let clocks = Tokens::new( (ctx.device.PMC, ctx.device.SUPC, ctx.device.UTMI), @@ -54,17 +55,21 @@ mod app { ); let led = banka.pa23.into_output(true); - let mono = Rtt::new_8192Hz(ctx.device.RTT, &slck).into_monotonic(); + // let mono = Rtt::new_8192Hz(ctx.device.RTT, &slck).into_monotonic(); - toggle_led::spawn().unwrap(); + // toggle_led::spawn().unwrap(); - (Shared {}, Local { led }, init::Monotonics(mono)) + (Shared {}, Local { led }, init::Monotonics()) } - #[task(local = [led])] - fn toggle_led(ctx: toggle_led::Context) { + #[idle(local = [led])] + fn idle(ctx: idle::Context)-> ! { + rprintln!("Idle"); ctx.local.led.toggle().unwrap(); - rprintln!("LED0 toggled"); - toggle_led::spawn_after(1.secs()).unwrap(); + loop { + rprintln!("Loop"); + ctx.local.led.toggle().unwrap(); + cortex_m::asm::delay(2000000); + } } } diff --git a/boards/atsamv71_xult/examples/blinky_irq.rs b/boards/atsamv71_xult/examples/blinky_irq.rs index 687af9c1..ac329c17 100644 --- a/boards/atsamv71_xult/examples/blinky_irq.rs +++ b/boards/atsamv71_xult/examples/blinky_irq.rs @@ -9,7 +9,7 @@ use panic_rtt_target as _; mod app { use atsamx7x_hal as hal; use hal::clocks::*; - use hal::efc::*; + use hal::efc::{Efc,VddioLevel}; use hal::ehal::digital::v2::ToggleableOutputPin; use hal::ehal::timer::CountDown; use hal::pio::*; diff --git a/boards/atsamv71_xult/examples/bootloader.rs b/boards/atsamv71_xult/examples/bootloader.rs new file mode 100644 index 00000000..a0be28b2 --- /dev/null +++ b/boards/atsamv71_xult/examples/bootloader.rs @@ -0,0 +1,172 @@ +#![no_std] +#![no_main] +use atsamx7x_hal as hal; +use cortex_m::asm::bootload; +use cortex_m_rt::entry; +use hal::efc::*; +use hal::pac; +use panic_halt as _; + +#[entry] +fn main() -> ! { + const BLINKY_ARRAY: [usize; 1024] = [ + 0x20440000, 0x420169, 0x4204e1, 0x4209f3, 0x4204e1, 0x4204e1, 0x4204e1, 0x0, 0x0, 0x0, 0x0, + 0x4204e1, 0x4204e1, 0x0, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, + 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x0, 0x4204e1, 0x4204e1, 0x4204e1, + 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, + 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, + 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, + 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, + 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x0, 0x0, 0x4204e1, 0x4204e1, 0x4204e1, + 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, + 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x34fff04f, 0xf00046a6, + 0x46a6f9b8, 0x490f480e, 0x42812200, 0xc004d001, 0x480de7fb, 0x4a0e490d, 0xd0024281, + 0xc008ca08, 0x480ce7fa, 0x170f44f, 0x430a6802, 0xf3bf6002, 0xf3bf8f4f, 0xb5008f6f, + 0xf866f000, 0xde00, 0x20400000, 0x20400440, 0x20400000, 0x20400000, 0x420a48, 0xe000ed88, + 0xbabff000, 0x466fb580, 0x2005b084, 0x4a30f240, 0xf6409001, 0xf2c02016, 0xf2c20042, + 0x90000a40, 0x4f8da, 0x8f5ff3bf, 0x4669b158, 0x21009103, 0x1008f88d, 0x5115f240, + 0xa8026802, 0x142f2c0, 0xf6404790, 0xf6406530, 0xf2c4281b, 0xf641050e, 0x68a83400, + 0xf2404629, 0xf10d5915, 0xf44f0b08, 0xf2c00600, 0xdc00842, 0x4b7f2c0, 0x182f360, 0x942f2c0, + 0xe008600e, 0x20068a8, 0xbf484628, 0x60063004, 0xf0004620, 0x2005fa80, 0x8000e9cd, 0x4f8da, + 0x8f5ff3bf, 0xd0ed2800, 0x91034669, 0xf88d2100, 0x46491008, 0x46586802, 0xe7e34790, + 0x466fb580, 0xffa4f7ff, 0xf803f000, 0xffa2f7ff, 0xb5f0defe, 0xe92daf03, 0xb0840b00, + 0x4400f240, 0x4930f240, 0x440f2c2, 0x940f2c2, 0x801f04f, 0x21304620, 0x8000f889, + 0xfb9df000, 0x2008f640, 0xf2c04626, 0xf2400042, 0xf8460200, 0xf44f0f18, 0x62206080, + 0x240f2c2, 0xf3bf6ae0, 0xf3bf8f5f, 0x25008f5f, 0x3f020, 0xf64062e0, 0xf3bf2020, 0xf2c08f5f, + 0x61e20042, 0x68007901, 0x8010f8c4, 0xf6406020, 0xf2c02028, 0x71210042, 0xe9d06165, + 0xf3bf1200, 0x68808f5f, 0xe9c460e0, 0xf0001201, 0x4604fa22, 0xfa15f000, 0xf88907e0, + 0xf8c9500c, 0xbf086008, 0xfa0ff000, 0x2034f640, 0x8f5ff3bf, 0x42f2c0, 0x4f8c9, 0xf3bf2005, + 0x90018f5f, 0x2011f640, 0x42f2c0, 0xf8d99000, 0xf3bf0004, 0xb1588f5f, 0x91034669, + 0xf88d2100, 0xf2401008, 0x68025115, 0xf2c0a802, 0x47900142, 0x10f641, 0x4100f44f, 0xef2c4, + 0x21086441, 0x5100f2ca, 0xf2406001, 0xf2c46068, 0xf64f000e, 0xf85071ff, 0xf6cf2c48, + 0xf1016100, 0x401313ff, 0x7201f64f, 0x237f2c0, 0xf8404313, 0x68033c48, 0xd10907db, + 0x7db6803, 0x6803bf04, 0x73c3ea5f, 0x6803d102, 0xd0f207db, 0x3c48f850, 0x12fff102, + 0x43114019, 0x1c48f840, 0x3c96801, 0x6801d409, 0xbf5c03c9, 0xea5f6801, 0xd40231c1, + 0x3c96801, 0xf640d5f2, 0xf24441e4, 0xf2c43300, 0xf2c4010e, 0x680a5346, 0x2fef002, + 0x600a431a, 0x2598f8d0, 0xf4222301, 0xf8c06270, 0xf8502598, 0xf3632c38, 0xf8400201, + 0x68022c38, 0xd4090712, 0x7126802, 0x6802bf5c, 0x7202ea5f, 0x6802d402, 0xd5f20712, + 0x2c38f850, 0x270f022, 0x2c38f840, 0x7126802, 0x6802d409, 0xbf5c0712, 0xea5f6802, + 0xd4027202, 0x7126802, 0xf850d5f2, 0xf4222c38, 0xf8407240, 0x68022c38, 0xd4090712, + 0x7126802, 0x6802bf5c, 0x7202ea5f, 0x6802d402, 0xd5f20712, 0x6280f44f, 0x2c58f840, + 0x2c50f850, 0xd40c0552, 0x2c50f850, 0xbf5c0552, 0x2c50f850, 0x5242ea5f, 0xf850d403, + 0x5522c50, 0x2000d5ee, 0x1a8f8c1, 0xf44f, 0x11cf8c1, 0x170f8c1, 0x12cf8c1, 0x14cf8c1, + 0xf93bf000, 0xe8bdb004, 0xbdf00b00, 0x4770e7fe, 0xaf03b5f0, 0xbd04f84d, 0x4605460c, + 0xf935f000, 0xf0004606, 0x4628f928, 0x7f047a0, 0xf85dd105, 0xe8bdbb04, 0xf00040f0, + 0xf85db920, 0xbdf0bb04, 0xaf03b5f0, 0xf00e92d, 0xf240b085, 0x78034230, 0x240f2c2, + 0x68e66894, 0x8f5ff3bf, 0xf3bf6925, 0x68a18f5f, 0xbf38428e, 0xd30a428d, 0xf3bf2600, + 0x60e68f5f, 0x8f5ff3bf, 0x8f5ff3bf, 0xf3bf6126, 0x7b118f5f, 0xc00f04f, 0x42999303, + 0x2200d101, 0x9001e075, 0x10ff003, 0xf6406890, 0xf2c02238, 0xf1a70242, 0x5c51091e, + 0x802f04f, 0xf3bf6940, 0xf8078f5f, 0x21ff1c1d, 0x3f000, 0x1c1ef807, 0xbf181ec1, 0xf1b14601, + 0xbf180b01, 0x43f0468b, 0xf3bf68e3, 0x69228f5f, 0x8f5ff3bf, 0x42ab68a5, 0x42aabf38, + 0xf3bfd30e, 0xf8c48f5f, 0xf3bfc00c, 0xf3bf8f5f, 0xf8c48f5f, 0xf3bfc010, 0x68a58f5f, + 0xe0074405, 0xd90142b2, 0xe0031815, 0xbf142a00, 0x44051bad, 0xbf884545, 0xb97d4645, + 0xf02f1bb, 0xf3bfd105, 0x60e68f5f, 0x8f5ff3bf, 0xf1bbe7d0, 0xd01c0f00, 0xf04f2001, + 0xe0010a00, 0x46aa2000, 0x68609002, 0x46524649, 0xf0004430, 0x68a0f8a1, 0xf04f4456, + 0x42860c00, 0x4666bf28, 0xf0002d00, 0x9a028088, 0xebb844d1, 0xd1b0080a, 0x2202e000, + 0x4030f240, 0xf2c29903, 0x73010040, 0x68409801, 0xb500e9d0, 0xf0006960, 0xf1b00003, + 0xbf180a03, 0x2a004682, 0x8f5ff3bf, 0x2d00d156, 0xf04fd054, 0xea6f0e00, 0x68e30c06, + 0x8f5ff3bf, 0xf3bf6922, 0x68a08f5f, 0xbf384283, 0xd30f4282, 0x8f5ff3bf, 0xe00cf8c4, + 0x8f5ff3bf, 0x8f5ff3bf, 0xe010f8c4, 0x8f5ff3bf, 0xeb0068a0, 0xe00a090c, 0xd90242b2, + 0x90ceb02, 0x2a00e005, 0xeba0bf14, 0xeb000906, 0x45a9090c, 0x46a9bf88, 0xf00f1b9, + 0xf1bad10e, 0xd1050f02, 0x8f5ff3bf, 0xf3bf60e6, 0xe7ca8f5f, 0xf00f1ba, 0xf04fd01a, + 0xe0000800, 0x686046c8, 0x46424659, 0xf0004430, 0x68a0f833, 0xf04f4446, 0x42860e00, + 0x4676bf28, 0xf00f1b9, 0x44c3bf1c, 0x508ebb5, 0xe00bd1ad, 0xd1092a02, 0x4030f240, + 0xf2c29903, 0x73010040, 0xe8bdb005, 0xbdf00f00, 0x8f5ff3bf, 0xf3bf60e6, 0xb0058f5f, + 0xf00e8bd, 0x9a02bdf0, 0xb672e77c, 0xb6624770, 0x21014770, 0x50eb01, 0xd1fd3801, + 0xf3ef4770, 0x47708010, 0xb800f000, 0xb84ef000, 0x4611460b, 0xf000461a, 0xb5d0b8ed, + 0x4613af02, 0x2904b2d2, 0x414d339, 0xe04f1a1, 0x6303ea44, 0xea432401, 0xeb042302, + 0x4413049e, 0x403f014, 0x4684d00a, 0xf84c2c01, 0xd10d3b04, 0x46714660, 0xf0cf1be, + 0xe002d219, 0xf0cf1be, 0x4660d215, 0x40d0e8bd, 0xbfd4f7ff, 0x60432c02, 0x3908d106, + 0x46843008, 0xf0cf1be, 0xe7f0d207, 0x390c6083, 0x4684300c, 0xf0cf1be, 0x3910d3e9, + 0x3300e9c0, 0x3302e9c0, 0x29033010, 0x4684d8f7, 0xe8bd4660, 0xf7ff40d0, 0x2200bfb5, + 0xbfb7f7ff, 0xaf03b5f0, 0x700e92d, 0xd9632a0f, 0xf0134243, 0xeb000403, 0xd0160c04, + 0x460e4603, 0xf8037835, 0x45635b01, 0x7875d20f, 0x5b01f803, 0xbf3e4563, 0xf80378b5, + 0x45635b01, 0x78f5d205, 0xf8033604, 0x45635b01, 0xeba2d3ea, 0xeb010e04, 0xf02e0904, + 0xeb0c0803, 0xea5f0308, 0xd03e7189, 0xf01f1b8, 0x2118db54, 0xac9ea01, 0x103f029, 0x6c9ea4f, + 0x508f101, 0x4271680a, 0x618f001, 0x1c04f855, 0xf20afa22, 0xf406fa01, 0xf84c4322, + 0x459c2b04, 0x682ad23c, 0xf10afa21, 0xf406fa02, 0xf84c4321, 0x459c1b04, 0x6869bf3f, + 0xf20afa22, 0xf406fa01, 0xbf3c4322, 0x2b04f84c, 0xd227459c, 0xfa2168aa, 0x3510f10a, + 0xf406fa02, 0xf84c4321, 0x459c1b04, 0xe01bd3d4, 0xb9f24603, 0xf1b8e033, 0xdb150f01, + 0x6821464c, 0x1b04f84c, 0xd20f459c, 0xf84c6861, 0x459c1b04, 0x68a1bf3e, 0x1b04f84c, + 0xd205459c, 0x341068e1, 0x1b04f84c, 0xd3ea459c, 0x108eb09, 0x203f00e, 0x441ab1aa, + 0xf803780e, 0x42936b01, 0x784ed20f, 0x6b01f803, 0xbf3e4293, 0xf803788e, 0x42936b01, + 0x78ced205, 0xf8033104, 0x42936b01, 0xe8bdd3ea, 0xbdf00700, 0xaf02b5d0, 0xd9362a0f, + 0xf0134243, 0xeb000e03, 0xd0100c0e, 0xf8034603, 0x45631b01, 0xf803d20b, 0x45631b01, + 0xf803bf3c, 0x45631b01, 0xf803d203, 0x45631b01, 0xeba2d3ef, 0xf02e0e0e, 0xeb0c0203, + 0x2a010302, 0xb2cadb13, 0x3401f04f, 0xf84c4362, 0x459c2b04, 0xf84cd20b, 0x459c2b04, + 0xf84cbf3c, 0x459c2b04, 0xf84cd203, 0x459c2b04, 0xf00ed3ef, 0xb9120203, 0x4603e012, + 0x441ab182, 0x1b01f803, 0xd20b4293, 0x1b01f803, 0xbf3c4293, 0x1b01f803, 0xd2034293, + 0x1b01f803, 0xd3ef4293, 0xf7ffbdd0, 0x4670bf08, 0x42082104, 0xf3efd102, 0xe0028008, + 0x8009f3ef, 0xe7fee7ff, 0x6d726554, 0x6c616e69, 0x696e4900, 0x64490a74, 0x4c0a656c, + 0xa706f6f, 0x47474553, 0x5f, 0x52205245, 0x5454, 0x0, 0x4204e5, 0x33323130, 0x37363534, + 0x42413938, 0x46454443, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + ]; + let efc = pac::Peripherals::take().unwrap().EFC; + let flash = Tokens::new(efc); + let mut sector1 = flash.sector1; + unsafe { + sector1.erase_sector(); + sector1.write_page(0, &BLINKY_ARRAY[0..128]).unwrap(); + sector1.write_page(1, &BLINKY_ARRAY[128..256]).unwrap(); + sector1.write_page(2, &BLINKY_ARRAY[256..384]).unwrap(); + sector1.write_page(3, &BLINKY_ARRAY[384..512]).unwrap(); + sector1.write_page(4, &BLINKY_ARRAY[512..640]).unwrap(); + sector1.write_page(5, &BLINKY_ARRAY[640..768]).unwrap(); + sector1.write_page(6, &BLINKY_ARRAY[768..896]).unwrap(); + sector1.write_page(7, &BLINKY_ARRAY[896..1024]).unwrap(); + + bootload(0x0420000 as *const u32); + } +} diff --git a/boards/atsamv71_xult/examples/efc.rs b/boards/atsamv71_xult/examples/efc.rs new file mode 100644 index 00000000..ee1de3f1 --- /dev/null +++ b/boards/atsamv71_xult/examples/efc.rs @@ -0,0 +1,63 @@ +//! Test that system io pins behave as expected +#![no_std] +#![no_main] + +use panic_rtt_target as _; + +#[rtic::app(device = hal::pac, peripherals = true, dispatchers = [UART0])] +mod app { + use atsamx7x_hal as hal; + use core::ptr; + use hal::efc::*; + use hal::ehal::digital::v2::ToggleableOutputPin; + use hal::pio::*; + use hal::rtt::*; + use rtt_target::{rprintln, rtt_init_print}; + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[init] + fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) { + rtt_init_print!(); + let mut efc = ctx.device.EFC; + let wdt = ctx.device.WDT; + wdt.wdt_mr.modify(|_, w| w.wddis().set_bit()); + rprintln!("0x{:x}", efc.eefc_fsr.read().bits()); + rprintln!("0x{:x}", efc.eefc_fmr.read().bits()); + let flash_tokens = Tokens::new(efc); + let sector0 = flash_tokens.sector0; + for i in 0..32768 { + rprintln!("Word 0x{:x}: 0x{:x}", i, sector0.read_word(i).unwrap()); + } + // let sector1 = flash_tokens.sector1; + // rprintln!("Reading Flash Sector 1..."); + // for i in 0..32768 { + // rprintln!("Word 0x{:x}: 0x{:x}", i, sector1.read_word(i).unwrap()); + // } + + let dead_beef: [usize; 128] = [0xdeadbeef; 128]; + let sector8 = flash_tokens.sector8; + unsafe { sector8.write_page(0, &dead_beef).unwrap() }; + unsafe { sector8.write_page(1, &dead_beef).unwrap() }; + unsafe { sector8.write_page(2, &dead_beef).unwrap() }; + unsafe { sector8.write_page(3, &dead_beef).unwrap() }; + for i in 8..12 { + rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); + } + rprintln!("Erasing Flash Sector..."); + unsafe { sector8.erase_sector().unwrap() }; + rprintln!("Flash Sector Erased"); + for i in 8..12 { + rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); + } + unsafe {sector8.write_word(0xbeefbeef,10).unwrap() }; + rprintln!("0x{:x}", sector8.read_word(10).unwrap()); + + (Shared {}, Local {}, init::Monotonics()) + } + +} diff --git a/boards/atsamv71_xult/examples/minimal-bootloader.rs b/boards/atsamv71_xult/examples/minimal-bootloader.rs new file mode 100644 index 00000000..12ee9b7a --- /dev/null +++ b/boards/atsamv71_xult/examples/minimal-bootloader.rs @@ -0,0 +1,15 @@ +#![no_std] +#![no_main] +use cortex_m::asm::bootload; +use atsamx7x_hal as hal; +use cortex_m_rt::entry; +use panic_halt as _; + +#[entry] +fn main() -> ! { + + unsafe { + bootload( 0x00420000 as *const u32); + } + +} diff --git a/hal/src/efc.rs b/hal/src/efc.rs index 74341cd4..7c441c5b 100644 --- a/hal/src/efc.rs +++ b/hal/src/efc.rs @@ -1,7 +1,19 @@ -//! Flash controller configuration +/*! +Flash controller configuration +--- + +The Enhanced Embedded Flash Controller peripheral (EFC) or (EEFC) provides the interface of the Flash block with the 32-bit internal bus. + +Two functions of the EFC are exposed in this HAL, the ability to set wait states, and the ability to reconfigure the flash memory. + +The wait states need to be reconfigured to allow for correct operation at higher clock frequencies and is normally handled by the [`Clock`] module. + + +*/ use crate::clocks::{ClockError, Megahertz}; -use crate::pac::EFC; +use crate::pac::{efc, EFC}; +use core::ptr; /// The voltage which drives the MCU. /// @@ -14,6 +26,237 @@ pub enum VddioLevel { V1, } +/// Set of [`Token`]s for device Flash Memory. +#[allow(missing_docs)] +pub struct Tokens { + pub sector0: Sector<0>, + pub sector1: Sector<1>, + pub sector2: Sector<2>, + pub sector3: Sector<3>, + #[cfg(not(feature = "flash-512K"))] + pub sector4: Sector<4>, + #[cfg(not(feature = "flash-512K"))] + pub sector5: Sector<5>, + #[cfg(not(feature = "flash-512K"))] + pub sector6: Sector<6>, + #[cfg(not(feature = "flash-512K"))] + pub sector7: Sector<7>, + #[cfg(feature = "flash-2M")] + pub sector8: Sector<8>, + #[cfg(feature = "flash-2M")] + pub sector9: Sector<9>, + #[cfg(feature = "flash-2M")] + pub sector10: Sector<10>, + #[cfg(feature = "flash-2M")] + pub sector11: Sector<11>, + #[cfg(feature = "flash-2M")] + pub sector12: Sector<12>, + #[cfg(feature = "flash-2M")] + pub sector13: Sector<13>, + #[cfg(feature = "flash-2M")] + pub sector14: Sector<14>, + #[cfg(feature = "flash-2M")] + pub sector15: Sector<15>, +} + +impl Tokens { + /// Create the set of all Flash Sector [`Token`]s. + pub fn new(_efc: EFC) -> Self { + Self { + sector0: Sector::new(), + sector1: Sector::new(), + sector2: Sector::new(), + sector3: Sector::new(), + #[cfg(not(feature = "flash-512K"))] + sector4: Sector::new(), + #[cfg(not(feature = "flash-512K"))] + sector5: Sector::new(), + #[cfg(not(feature = "flash-512K"))] + sector6: Sector::new(), + #[cfg(not(feature = "flash-512K"))] + sector7: Sector::new(), + #[cfg(feature = "flash-2M")] + sector8: Sector::new(), + #[cfg(feature = "flash-2M")] + sector9: Sector::new(), + #[cfg(feature = "flash-2M")] + sector10: Sector::new(), + #[cfg(feature = "flash-2M")] + sector11: Sector::new(), + #[cfg(feature = "flash-2M")] + sector12: Sector::new(), + #[cfg(feature = "flash-2M")] + sector13: Sector::new(), + #[cfg(feature = "flash-2M")] + sector14: Sector::new(), + #[cfg(feature = "flash-2M")] + sector15: Sector::new(), + } + } +} + +/// Struct representing a sector of Flash Memory +pub struct Sector {} +/// Error Enum, Big WIP on this one. +#[derive(Debug, Copy, Clone)] +pub enum Error { + /// Access Outside Of the Flash Sector + SectorRangeError, + /// Attempted to execute a command when eefc is busy + FlashBusyError, + /// An invalid Command and/or a bad keyword was/were written in EEFC_FMR + FlashCommandError, + /// Programming/erase of at least one locked region has happened. + FlashLockError, + /// A Flash memory error occured at the end of programming (EraseVerify or WriteVerify + /// test has failed). + FlashError, + /// MultiError MSB + MultipleEccErrorMsb, + /// MultiEccErrorLsb + MultipleEccErrorLsb, + /// UniqueError MSB + UniqueEccErrorMsb, + /// UniqueEccErrorLsb + UniqueEccErrorLsb, +} + +impl From for Error { + fn from(x: u32) -> Error { + if x & 0x00000002 != 0 { + Error::FlashCommandError + } else if x & 0x00000004 != 0 { + Error::FlashLockError + } else if x & 0x00000008 != 0 { + Error::FlashError + } else if x & 0x00010000 != 0 { + Error::UniqueEccErrorLsb + } else if x & 0x00020000 != 0 { + Error::MultipleEccErrorLsb + } else if x & 0x00040000 != 0 { + Error::UniqueEccErrorMsb + } else if x & 0x00080000 != 0 { + Error::MultipleEccErrorMsb + } else { + panic!("Unknown Error") + } + } +} + +/// Token Representing a sector in flash memory +impl Sector { + /// Read a single 32 bit word from a flash sector. + pub fn read_word(&self, offset: usize) -> Result { + // Check that offset is still within range of the sector + if offset > 32767 { + return Err(Error::SectorRangeError); + } + Ok(unsafe { ptr::read_volatile(self.addr().offset(offset.try_into().unwrap())) }) + } + + /// Erase the entire sector. + /// Safety: Erasing Flash is fundamentally unsafe. + pub unsafe fn erase_sector(&self) -> Result<(), Error> { + if self.efc().eefc_fsr.read().frdy().bit_is_clear() { + return Err(Error::FlashBusyError); + } + self.efc().eefc_fcr.write(|w| { + w.fkey().passwd(); + w.fcmd().es(); + w.farg().bits((256_u16 * (N as u16)) as u16); + w + }); + loop { + let status = self.efc().eefc_fsr.read(); + // Wait until frdy is set + if status.bits() == 0x00000001 { + return Ok(()); + } + // If an error is detected, return + else if status.bits() != 0x00000000 { + return Err(status.bits().into()); + } + } + } + + /// Write page to flash memory. + /// Safety: Writing to Flash is fundamentally unsafe. + pub unsafe fn write_page(&self, page: u16, data: &[usize]) -> Result<(), Error> { + if page > 255 { + return Err(Error::SectorRangeError); + } + if self.efc().eefc_fsr.read().frdy().bit_is_clear() { + return Err(Error::FlashBusyError); + } + self.addr() + .offset((page * 512) as isize) + .copy_from(data.as_ptr(), 128); + + self.efc().eefc_fcr.write(|w| { + w.fkey().passwd(); + w.fcmd().wp(); + w.farg().bits(256_u16 * (N as u16) + page); + w + }); + loop { + let status = self.efc().eefc_fsr.read(); + // Wait until frdy is set + if status.bits() == 0x00000001 { + return Ok(()); + } + // If an error is detected, return + else if status.bits() != 0x00000000 { + return Err(status.bits().into()); + } + } + } + + /// Write single 32-bit word to flash memory. + /// Safety: Writing to Flash is fundamentally unsafe. + pub unsafe fn write_word(&self, word: usize, offset: u16) -> Result<(), Error> { + if offset > 32767 { + return Err(Error::SectorRangeError); + } + if self.efc().eefc_fsr.read().frdy().bit_is_clear() { + return Err(Error::FlashBusyError); + } + self.addr().offset(offset as isize).write_volatile(word); + self.efc().eefc_fcr.write(|w| { + w.fkey().passwd(); + w.fcmd().wp(); + w.farg().bits(256_u16 * (N as u16) + (offset/128)); + w + }); + loop { + let status = self.efc().eefc_fsr.read(); + // Wait until frdy is set + if status.bits() == 0x00000001 { + return Ok(()); + } + // If an error is detected, return + else if status.bits() != 0x00000000 { + return Err(status.bits().into()); + } + } + } + + fn new() -> Self { + Self {} + } +} + +unsafe trait RegisterAccess { + #[inline(always)] + fn addr(&self) -> *mut usize { + unsafe { (0x400000 + (N as usize) * 0x20000) as *mut usize } + } + + fn efc(&self) -> &efc::RegisterBlock { + unsafe { &*EFC::ptr() } + } +} + +unsafe impl RegisterAccess for Sector {} /// [`EFC`] abstraction. pub struct Efc { pub(crate) periph: EFC, @@ -23,7 +266,7 @@ pub struct Efc { impl Efc { /// Creates a new [`Efc`], the behavior of which depends on the /// voltage, [`VddioLevel`], that drives the MCU. - pub fn new(periph: EFC, vddio: VddioLevel) -> Self { + pub fn new(periph: EFC, vddio: VddioLevel) -> (Self) { periph.eefc_wpmr.modify(|_r, w| { w.wpkey().passwd(); w.wpen().clear_bit(); From 282df25b4d3a4bcfe1de73f4c3f34ee58361fb5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6rtsell?= Date: Tue, 15 Aug 2023 16:54:35 +0200 Subject: [PATCH 2/8] Refractor Flash API, Move Sectors Struct Into Efc Struct Update `efc.rs` Example Add Flash Sector Tokens and read_word Funcitonality (WIP) Add Erase Sector Method Add Write Page Method Add Write Word Method Refractor Flash API, Move Sectors Struct Into Efc Struct Update `efc.rs` Example Fix Issues Causing `docs` Generation To Fail Fix Clippy Lints Fix Issues With `atsamv71_xult` Examples Run `cargo fmt` Run `cargo fmt` On Examples --- boards/atsame70_xpro/examples/efc.rs | 67 +++++++++++++++++++ boards/atsamv71_xult/examples/blinky.rs | 2 +- boards/atsamv71_xult/examples/blinky_irq.rs | 2 +- boards/atsamv71_xult/examples/bootloader.rs | 38 ++++++++--- boards/atsamv71_xult/examples/efc.rs | 46 +++++++------ .../examples/minimal-bootloader.rs | 15 ----- hal/src/efc.rs | 56 ++++++++++------ 7 files changed, 154 insertions(+), 72 deletions(-) create mode 100644 boards/atsame70_xpro/examples/efc.rs delete mode 100644 boards/atsamv71_xult/examples/minimal-bootloader.rs diff --git a/boards/atsame70_xpro/examples/efc.rs b/boards/atsame70_xpro/examples/efc.rs new file mode 100644 index 00000000..1e6cbe9b --- /dev/null +++ b/boards/atsame70_xpro/examples/efc.rs @@ -0,0 +1,67 @@ +//! Test that system io pins behave as expected +#![no_std] +#![no_main] + +use panic_rtt_target as _; + +#[rtic::app(device = hal::pac, peripherals = true, dispatchers = [UART0])] +mod app { + use atsamx7x_hal as hal; + use hal::efc::*; + use rtt_target::{rprintln, rtt_init_print}; + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[init] + fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) { + rtt_init_print!(); + let efc = ctx.device.EFC; + let wdt = ctx.device.WDT; + wdt.mr.modify(|_, w| w.wddis().set_bit()); + rprintln!("0x{:x}", efc.eefc_fsr.read().bits()); + rprintln!("0x{:x}", efc.eefc_fmr.read().bits()); + let flash_sectors = Efc::new(efc, VddioLevel::V3).sectors; + let sector0 = flash_sectors.sector0; + for i in 0..32768 { + rprintln!("Word 0x{:x}: 0x{:x}", i, sector0.read_word(i).unwrap()); + } + // let sector1 = flash_tokens.sector1; + // rprintln!("Reading Flash Sector 1..."); + // for i in 0..32768 { + // rprintln!("Word 0x{:x}: 0x{:x}", i, sector1.read_word(i).unwrap()); + // } + + let dead_beef: [usize; 128] = [0xdeadbeef; 128]; + let sector8 = flash_sectors.sector8; + for _j in 0..10 { + unsafe { sector8.write_page(0, &dead_beef).unwrap() }; + unsafe { sector8.write_page(1, &dead_beef).unwrap() }; + unsafe { sector8.write_page(2, &dead_beef).unwrap() }; + unsafe { sector8.write_page(3, &dead_beef).unwrap() }; + for i in 8..12 { + rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); + } + rprintln!("Erasing Flash Sector..."); + unsafe { sector8.erase_sector().unwrap() }; + rprintln!("Flash Sector Erased"); + for i in 8..12 { + rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); + } + } + unsafe { sector8.write_page(0, &dead_beef).unwrap() }; + unsafe { sector8.write_page(1, &dead_beef).unwrap() }; + unsafe { sector8.write_page(2, &dead_beef).unwrap() }; + unsafe { sector8.write_page(3, &dead_beef).unwrap() }; + for i in 8..12 { + rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); + } + unsafe { sector8.write_word(0xbeefbeef, 10).unwrap() }; + rprintln!("0x{:x}", sector8.read_word(10).unwrap()); + + (Shared {}, Local {}, init::Monotonics()) + } +} diff --git a/boards/atsamv71_xult/examples/blinky.rs b/boards/atsamv71_xult/examples/blinky.rs index f8f2c9e0..b460860e 100644 --- a/boards/atsamv71_xult/examples/blinky.rs +++ b/boards/atsamv71_xult/examples/blinky.rs @@ -63,7 +63,7 @@ mod app { } #[idle(local = [led])] - fn idle(ctx: idle::Context)-> ! { + fn idle(ctx: idle::Context) -> ! { rprintln!("Idle"); ctx.local.led.toggle().unwrap(); loop { diff --git a/boards/atsamv71_xult/examples/blinky_irq.rs b/boards/atsamv71_xult/examples/blinky_irq.rs index ac329c17..bdf6e803 100644 --- a/boards/atsamv71_xult/examples/blinky_irq.rs +++ b/boards/atsamv71_xult/examples/blinky_irq.rs @@ -9,7 +9,7 @@ use panic_rtt_target as _; mod app { use atsamx7x_hal as hal; use hal::clocks::*; - use hal::efc::{Efc,VddioLevel}; + use hal::efc::{Efc, VddioLevel}; use hal::ehal::digital::v2::ToggleableOutputPin; use hal::ehal::timer::CountDown; use hal::pio::*; diff --git a/boards/atsamv71_xult/examples/bootloader.rs b/boards/atsamv71_xult/examples/bootloader.rs index a0be28b2..342f6964 100644 --- a/boards/atsamv71_xult/examples/bootloader.rs +++ b/boards/atsamv71_xult/examples/bootloader.rs @@ -154,18 +154,34 @@ fn main() -> ! { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, ]; let efc = pac::Peripherals::take().unwrap().EFC; - let flash = Tokens::new(efc); - let mut sector1 = flash.sector1; + let flash_sectors = Efc::new(efc, VddioLevel::V3).sectors; + let sector1 = flash_sectors.sector1; unsafe { - sector1.erase_sector(); - sector1.write_page(0, &BLINKY_ARRAY[0..128]).unwrap(); - sector1.write_page(1, &BLINKY_ARRAY[128..256]).unwrap(); - sector1.write_page(2, &BLINKY_ARRAY[256..384]).unwrap(); - sector1.write_page(3, &BLINKY_ARRAY[384..512]).unwrap(); - sector1.write_page(4, &BLINKY_ARRAY[512..640]).unwrap(); - sector1.write_page(5, &BLINKY_ARRAY[640..768]).unwrap(); - sector1.write_page(6, &BLINKY_ARRAY[768..896]).unwrap(); - sector1.write_page(7, &BLINKY_ARRAY[896..1024]).unwrap(); + sector1.erase_sector().unwrap(); + sector1 + .write_page(0, &BLINKY_ARRAY[0..128].try_into().unwrap()) + .unwrap(); + sector1 + .write_page(1, &BLINKY_ARRAY[128..256].try_into().unwrap()) + .unwrap(); + sector1 + .write_page(2, &BLINKY_ARRAY[256..384].try_into().unwrap()) + .unwrap(); + sector1 + .write_page(3, &BLINKY_ARRAY[384..512].try_into().unwrap()) + .unwrap(); + sector1 + .write_page(4, &BLINKY_ARRAY[512..640].try_into().unwrap()) + .unwrap(); + sector1 + .write_page(5, &BLINKY_ARRAY[640..768].try_into().unwrap()) + .unwrap(); + sector1 + .write_page(6, &BLINKY_ARRAY[768..896].try_into().unwrap()) + .unwrap(); + sector1 + .write_page(7, &BLINKY_ARRAY[896..1024].try_into().unwrap()) + .unwrap(); bootload(0x0420000 as *const u32); } diff --git a/boards/atsamv71_xult/examples/efc.rs b/boards/atsamv71_xult/examples/efc.rs index ee1de3f1..a9455f55 100644 --- a/boards/atsamv71_xult/examples/efc.rs +++ b/boards/atsamv71_xult/examples/efc.rs @@ -7,12 +7,10 @@ use panic_rtt_target as _; #[rtic::app(device = hal::pac, peripherals = true, dispatchers = [UART0])] mod app { use atsamx7x_hal as hal; - use core::ptr; use hal::efc::*; - use hal::ehal::digital::v2::ToggleableOutputPin; - use hal::pio::*; - use hal::rtt::*; use rtt_target::{rprintln, rtt_init_print}; + use core::ptr; + #[shared] struct Shared {} @@ -23,24 +21,34 @@ mod app { #[init] fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) { rtt_init_print!(); - let mut efc = ctx.device.EFC; + let efc = ctx.device.EFC; let wdt = ctx.device.WDT; - wdt.wdt_mr.modify(|_, w| w.wddis().set_bit()); + wdt.mr.modify(|_, w| w.wddis().set_bit()); rprintln!("0x{:x}", efc.eefc_fsr.read().bits()); rprintln!("0x{:x}", efc.eefc_fmr.read().bits()); - let flash_tokens = Tokens::new(efc); - let sector0 = flash_tokens.sector0; + let flash_sectors = Efc::new(efc, VddioLevel::V3).sectors; + let sector0 = flash_sectors.sector0; for i in 0..32768 { rprintln!("Word 0x{:x}: 0x{:x}", i, sector0.read_word(i).unwrap()); } - // let sector1 = flash_tokens.sector1; - // rprintln!("Reading Flash Sector 1..."); - // for i in 0..32768 { - // rprintln!("Word 0x{:x}: 0x{:x}", i, sector1.read_word(i).unwrap()); - // } let dead_beef: [usize; 128] = [0xdeadbeef; 128]; - let sector8 = flash_tokens.sector8; + let sector8 = flash_sectors.sector8; + for _j in 0..10 { + unsafe { sector8.write_page(0, &dead_beef).unwrap() }; + unsafe { sector8.write_page(1, &dead_beef).unwrap() }; + unsafe { sector8.write_page(2, &dead_beef).unwrap() }; + unsafe { sector8.write_page(3, &dead_beef).unwrap() }; + for i in 8..12 { + rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); + } + rprintln!("Erasing Flash Sector..."); + unsafe { sector8.erase_sector().unwrap() }; + rprintln!("Flash Sector Erased"); + for i in 8..12 { + rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); + } + } unsafe { sector8.write_page(0, &dead_beef).unwrap() }; unsafe { sector8.write_page(1, &dead_beef).unwrap() }; unsafe { sector8.write_page(2, &dead_beef).unwrap() }; @@ -48,16 +56,10 @@ mod app { for i in 8..12 { rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); } - rprintln!("Erasing Flash Sector..."); - unsafe { sector8.erase_sector().unwrap() }; - rprintln!("Flash Sector Erased"); - for i in 8..12 { - rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); - } - unsafe {sector8.write_word(0xbeefbeef,10).unwrap() }; + unsafe { sector8.write_word(0xbeefbeef, 10).unwrap() }; rprintln!("0x{:x}", sector8.read_word(10).unwrap()); + (Shared {}, Local {}, init::Monotonics()) } - } diff --git a/boards/atsamv71_xult/examples/minimal-bootloader.rs b/boards/atsamv71_xult/examples/minimal-bootloader.rs deleted file mode 100644 index 12ee9b7a..00000000 --- a/boards/atsamv71_xult/examples/minimal-bootloader.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![no_std] -#![no_main] -use cortex_m::asm::bootload; -use atsamx7x_hal as hal; -use cortex_m_rt::entry; -use panic_halt as _; - -#[entry] -fn main() -> ! { - - unsafe { - bootload( 0x00420000 as *const u32); - } - -} diff --git a/hal/src/efc.rs b/hal/src/efc.rs index 7c441c5b..d6202d2a 100644 --- a/hal/src/efc.rs +++ b/hal/src/efc.rs @@ -1,4 +1,4 @@ -/*! +/*! Flash controller configuration --- @@ -6,7 +6,7 @@ The Enhanced Embedded Flash Controller peripheral (EFC) or (EEFC) provides the i Two functions of the EFC are exposed in this HAL, the ability to set wait states, and the ability to reconfigure the flash memory. -The wait states need to be reconfigured to allow for correct operation at higher clock frequencies and is normally handled by the [`Clock`] module. +The wait states need to be reconfigured to allow for correct operation at higher clock frequencies and is normally handled by the [clocks](crate::clocks) module. */ @@ -26,9 +26,9 @@ pub enum VddioLevel { V1, } -/// Set of [`Token`]s for device Flash Memory. +/// Set of [`Sector`]s for device Flash Memory. #[allow(missing_docs)] -pub struct Tokens { +pub struct Sectors { pub sector0: Sector<0>, pub sector1: Sector<1>, pub sector2: Sector<2>, @@ -59,9 +59,9 @@ pub struct Tokens { pub sector15: Sector<15>, } -impl Tokens { +impl Sectors { /// Create the set of all Flash Sector [`Token`]s. - pub fn new(_efc: EFC) -> Self { + fn new() -> Self { Self { sector0: Sector::new(), sector1: Sector::new(), @@ -90,7 +90,7 @@ impl Tokens { #[cfg(feature = "flash-2M")] sector14: Sector::new(), #[cfg(feature = "flash-2M")] - sector15: Sector::new(), + sector15: Sector::new() } } } @@ -155,7 +155,9 @@ impl Sector { } /// Erase the entire sector. - /// Safety: Erasing Flash is fundamentally unsafe. + /// # Safety + /// + /// Do not erase a flash sector where you are exectuing code. pub unsafe fn erase_sector(&self) -> Result<(), Error> { if self.efc().eefc_fsr.read().frdy().bit_is_clear() { return Err(Error::FlashBusyError); @@ -180,22 +182,21 @@ impl Sector { } /// Write page to flash memory. - /// Safety: Writing to Flash is fundamentally unsafe. - pub unsafe fn write_page(&self, page: u16, data: &[usize]) -> Result<(), Error> { - if page > 255 { - return Err(Error::SectorRangeError); - } + /// # Safety + /// + /// Do not erase a flash sector where you are exectuing code. + pub unsafe fn write_page(&self, page: u8, data: &[usize; 128]) -> Result<(), Error> { if self.efc().eefc_fsr.read().frdy().bit_is_clear() { return Err(Error::FlashBusyError); } self.addr() - .offset((page * 512) as isize) + .offset(((page as u16) * 512) as isize) .copy_from(data.as_ptr(), 128); self.efc().eefc_fcr.write(|w| { w.fkey().passwd(); w.fcmd().wp(); - w.farg().bits(256_u16 * (N as u16) + page); + w.farg().bits(256_u16 * (N as u16) + (page as u16)); w }); loop { @@ -212,7 +213,9 @@ impl Sector { } /// Write single 32-bit word to flash memory. - /// Safety: Writing to Flash is fundamentally unsafe. + /// # Safety + /// + /// Do not write to a flash sector where you are executing code. pub unsafe fn write_word(&self, word: usize, offset: u16) -> Result<(), Error> { if offset > 32767 { return Err(Error::SectorRangeError); @@ -224,7 +227,7 @@ impl Sector { self.efc().eefc_fcr.write(|w| { w.fkey().passwd(); w.fcmd().wp(); - w.farg().bits(256_u16 * (N as u16) + (offset/128)); + w.farg().bits(256_u16 * (N as u16) + (offset / 128)); w }); loop { @@ -243,12 +246,13 @@ impl Sector { fn new() -> Self { Self {} } + } -unsafe trait RegisterAccess { +trait RegisterAccess { #[inline(always)] fn addr(&self) -> *mut usize { - unsafe { (0x400000 + (N as usize) * 0x20000) as *mut usize } + (0x400000 + (N as usize) * 0x20000) as *mut usize } fn efc(&self) -> &efc::RegisterBlock { @@ -256,24 +260,31 @@ unsafe trait RegisterAccess { } } -unsafe impl RegisterAccess for Sector {} +impl RegisterAccess for Sector {} /// [`EFC`] abstraction. pub struct Efc { pub(crate) periph: EFC, vddio: VddioLevel, + /// struct representing the flash memory sectors. + pub sectors: Sectors, } impl Efc { /// Creates a new [`Efc`], the behavior of which depends on the /// voltage, [`VddioLevel`], that drives the MCU. - pub fn new(periph: EFC, vddio: VddioLevel) -> (Self) { + pub fn new(periph: EFC, vddio: VddioLevel) -> Self { periph.eefc_wpmr.modify(|_r, w| { w.wpkey().passwd(); w.wpen().clear_bit(); w }); + let sectors = Sectors::new(); - Self { periph, vddio } + Self { + periph, + vddio, + sectors, + } } /// Calculates and sets the lowest possible number of flash wait @@ -352,3 +363,4 @@ impl FlashWaitStates { } } } + From d3ef3161fa90f4cad17c3fdb4b9df625bb5e7c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6rtsell?= Date: Fri, 18 Aug 2023 17:53:29 +0200 Subject: [PATCH 3/8] Implement `embedded-storage` Flash API Remove Dead Code Conform To Clippy And Rusfmt Update Examples Update `CHANGELOG.md` Run `fmt` On Examples --- CHANGELOG.md | 1 + boards/atsame70_xpro/Cargo.lock | 18 ++ boards/atsame70_xpro/Cargo.toml | 1 + boards/atsame70_xpro/examples/efc.rs | 53 ++-- boards/atsamv71_xult/Cargo.lock | 8 + boards/atsamv71_xult/Cargo.toml | 1 + boards/atsamv71_xult/examples/bootloader.rs | 39 +-- boards/atsamv71_xult/examples/efc.rs | 50 ++-- hal/Cargo.toml | 1 + hal/src/efc.rs | 308 +++++++++++--------- 10 files changed, 262 insertions(+), 218 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14705044..537a26e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - [Integration](https://crates.io/crates/mcan-core) with the [`mcan`](https://crates.io/crates/mcan) crate. - Implementation of blocking::i2c::Transactional trait from [embedded-hal](https://crates.io/crates/embedded-hal) for TWI device. +- Implementation of ReadNorFlash and NorFlash traits from [embedded-storage](https://crates.io/crates/embedded-storage) for EFC. ### Changed diff --git a/boards/atsame70_xpro/Cargo.lock b/boards/atsame70_xpro/Cargo.lock index a693e1e9..13dc7844 100644 --- a/boards/atsame70_xpro/Cargo.lock +++ b/boards/atsame70_xpro/Cargo.lock @@ -27,6 +27,7 @@ dependencies = [ "atsamx7x-hal", "cortex-m", "cortex-m-rtic", + "embedded-storage", "heapless", "panic-halt", "panic-rtt-target", @@ -52,7 +53,9 @@ dependencies = [ "cfg-if", "cortex-m", "embedded-hal", + "embedded-storage", "fugit", + "mcan-core", "nb 1.0.0", "paste", "rtic-monotonic", @@ -194,6 +197,12 @@ dependencies = [ "void", ] +[[package]] +name = "embedded-storage" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "156d7a2fdd98ebbf9ae579cbceca3058cff946e13f8e17b90e3511db0508c723" + [[package]] name = "fugit" version = "0.3.6" @@ -272,6 +281,15 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "mcan-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b3dee4ff5269e2465cc856d37103cce916c1ef73b4377f006c963872e69f7ca" +dependencies = [ + "fugit", +] + [[package]] name = "memchr" version = "2.5.0" diff --git a/boards/atsame70_xpro/Cargo.toml b/boards/atsame70_xpro/Cargo.toml index ad85e4d3..e5024aed 100644 --- a/boards/atsame70_xpro/Cargo.toml +++ b/boards/atsame70_xpro/Cargo.toml @@ -15,6 +15,7 @@ panic-rtt-target = { version = "0.1.2", features = ["cortex-m"] } rtt-target = { version = "0.3.1", features = ["cortex-m"] } usbd-serial = "0.1.1" heapless = "0.7" +embedded-storage = "0.3" [dependencies.atsamx7x-hal] version = "0.4.2" diff --git a/boards/atsame70_xpro/examples/efc.rs b/boards/atsame70_xpro/examples/efc.rs index 1e6cbe9b..03973ed3 100644 --- a/boards/atsame70_xpro/examples/efc.rs +++ b/boards/atsame70_xpro/examples/efc.rs @@ -7,6 +7,8 @@ use panic_rtt_target as _; #[rtic::app(device = hal::pac, peripherals = true, dispatchers = [UART0])] mod app { use atsamx7x_hal as hal; + use embedded_storage::nor_flash::NorFlash; + use embedded_storage::nor_flash::ReadNorFlash; use hal::efc::*; use rtt_target::{rprintln, rtt_init_print}; @@ -20,47 +22,42 @@ mod app { fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) { rtt_init_print!(); let efc = ctx.device.EFC; - let wdt = ctx.device.WDT; - wdt.mr.modify(|_, w| w.wddis().set_bit()); rprintln!("0x{:x}", efc.eefc_fsr.read().bits()); rprintln!("0x{:x}", efc.eefc_fmr.read().bits()); - let flash_sectors = Efc::new(efc, VddioLevel::V3).sectors; - let sector0 = flash_sectors.sector0; + let mut efc = Efc::new(efc, VddioLevel::V3); + let wdt = ctx.device.WDT; + wdt.mr.modify(|_, w| w.wddis().set_bit()); + let mut a: [u8; 4] = [0; 4]; for i in 0..32768 { - rprintln!("Word 0x{:x}: 0x{:x}", i, sector0.read_word(i).unwrap()); + efc.read(i * 4, &mut a).unwrap(); + let a_int: u32 = u32::from_be_bytes(a); + rprintln!("Word 0x{:x}: 0x{:x}", i, a_int); } - // let sector1 = flash_tokens.sector1; - // rprintln!("Reading Flash Sector 1..."); - // for i in 0..32768 { - // rprintln!("Word 0x{:x}: 0x{:x}", i, sector1.read_word(i).unwrap()); - // } - let dead_beef: [usize; 128] = [0xdeadbeef; 128]; - let sector8 = flash_sectors.sector8; + let array: [u8; 512] = [0xad; 512]; for _j in 0..10 { - unsafe { sector8.write_page(0, &dead_beef).unwrap() }; - unsafe { sector8.write_page(1, &dead_beef).unwrap() }; - unsafe { sector8.write_page(2, &dead_beef).unwrap() }; - unsafe { sector8.write_page(3, &dead_beef).unwrap() }; + efc.write(SECTOR_SIZE as u32 * 8, &array).unwrap(); + efc.write(SECTOR_SIZE as u32 * 8 + PAGE_SIZE as u32, &array) + .unwrap(); + efc.write(SECTOR_SIZE as u32 * 8 + 2 * PAGE_SIZE as u32, &array) + .unwrap(); + efc.write(SECTOR_SIZE as u32 * 8 + 3 * PAGE_SIZE as u32, &array) + .unwrap(); for i in 8..12 { - rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); + efc.read(SECTOR_SIZE as u32 * 8 + i * 4, &mut a).unwrap(); + let a_int: u32 = u32::from_be_bytes(a); + rprintln!("Word 0x{:x}: 0x{:x}", i, a_int); } rprintln!("Erasing Flash Sector..."); - unsafe { sector8.erase_sector().unwrap() }; + efc.erase(SECTOR_SIZE as u32 * 8, SECTOR_SIZE as u32 * 9) + .unwrap(); rprintln!("Flash Sector Erased"); for i in 8..12 { - rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); + efc.read(SECTOR_SIZE as u32 * 8 + i * 4, &mut a).unwrap(); + let a_int: u32 = u32::from_be_bytes(a); + rprintln!("Word 0x{:x}: 0x{:x}", i, a_int); } } - unsafe { sector8.write_page(0, &dead_beef).unwrap() }; - unsafe { sector8.write_page(1, &dead_beef).unwrap() }; - unsafe { sector8.write_page(2, &dead_beef).unwrap() }; - unsafe { sector8.write_page(3, &dead_beef).unwrap() }; - for i in 8..12 { - rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); - } - unsafe { sector8.write_word(0xbeefbeef, 10).unwrap() }; - rprintln!("0x{:x}", sector8.read_word(10).unwrap()); (Shared {}, Local {}, init::Monotonics()) } diff --git a/boards/atsamv71_xult/Cargo.lock b/boards/atsamv71_xult/Cargo.lock index 6c0d51a5..f087fa71 100644 --- a/boards/atsamv71_xult/Cargo.lock +++ b/boards/atsamv71_xult/Cargo.lock @@ -29,6 +29,7 @@ dependencies = [ "cortex-m-rt", "cortex-m-rtic", "dwt-systick-monotonic", + "embedded-storage", "heapless", "mcan", "panic-halt", @@ -56,6 +57,7 @@ dependencies = [ "cfg-if", "cortex-m", "embedded-hal", + "embedded-storage", "fugit", "mcan-core", "nb 1.0.0", @@ -226,6 +228,12 @@ dependencies = [ "void", ] +[[package]] +name = "embedded-storage" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "156d7a2fdd98ebbf9ae579cbceca3058cff946e13f8e17b90e3511db0508c723" + [[package]] name = "fugit" version = "0.3.6" diff --git a/boards/atsamv71_xult/Cargo.toml b/boards/atsamv71_xult/Cargo.toml index 122ab190..101b1b4f 100644 --- a/boards/atsamv71_xult/Cargo.toml +++ b/boards/atsamv71_xult/Cargo.toml @@ -17,6 +17,7 @@ rtt-target = { version = "0.3.1", features = ["cortex-m"] } heapless = "0.7" usbd-serial = "0.1.1" dwt-systick-monotonic = "1.0.0" +embedded-storage = "0.3" [dev-dependencies] mcan = "0.2" diff --git a/boards/atsamv71_xult/examples/bootloader.rs b/boards/atsamv71_xult/examples/bootloader.rs index 342f6964..1d824e30 100644 --- a/boards/atsamv71_xult/examples/bootloader.rs +++ b/boards/atsamv71_xult/examples/bootloader.rs @@ -3,13 +3,14 @@ use atsamx7x_hal as hal; use cortex_m::asm::bootload; use cortex_m_rt::entry; +use embedded_storage::nor_flash::NorFlash; use hal::efc::*; use hal::pac; use panic_halt as _; #[entry] fn main() -> ! { - const BLINKY_ARRAY: [usize; 1024] = [ + const BLINKY_ARRAY: [u32; 1024] = [ 0x20440000, 0x420169, 0x4204e1, 0x4209f3, 0x4204e1, 0x4204e1, 0x4204e1, 0x0, 0x0, 0x0, 0x0, 0x4204e1, 0x4204e1, 0x0, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x4204e1, 0x0, 0x4204e1, 0x4204e1, 0x4204e1, @@ -153,36 +154,16 @@ fn main() -> ! { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, ]; + // transmute into u8 array + let blinky_array: [u8; 4096] = unsafe { core::mem::transmute(BLINKY_ARRAY) }; let efc = pac::Peripherals::take().unwrap().EFC; - let flash_sectors = Efc::new(efc, VddioLevel::V3).sectors; - let sector1 = flash_sectors.sector1; - unsafe { - sector1.erase_sector().unwrap(); - sector1 - .write_page(0, &BLINKY_ARRAY[0..128].try_into().unwrap()) - .unwrap(); - sector1 - .write_page(1, &BLINKY_ARRAY[128..256].try_into().unwrap()) - .unwrap(); - sector1 - .write_page(2, &BLINKY_ARRAY[256..384].try_into().unwrap()) - .unwrap(); - sector1 - .write_page(3, &BLINKY_ARRAY[384..512].try_into().unwrap()) - .unwrap(); - sector1 - .write_page(4, &BLINKY_ARRAY[512..640].try_into().unwrap()) - .unwrap(); - sector1 - .write_page(5, &BLINKY_ARRAY[640..768].try_into().unwrap()) - .unwrap(); - sector1 - .write_page(6, &BLINKY_ARRAY[768..896].try_into().unwrap()) - .unwrap(); - sector1 - .write_page(7, &BLINKY_ARRAY[896..1024].try_into().unwrap()) - .unwrap(); + let mut efc = Efc::new(efc, VddioLevel::V3); + + efc.erase(SECTOR_SIZE as u32, 2 * SECTOR_SIZE as u32) + .unwrap(); + efc.write(SECTOR_SIZE as u32, &blinky_array).unwrap(); + unsafe { bootload(0x0420000 as *const u32); } } diff --git a/boards/atsamv71_xult/examples/efc.rs b/boards/atsamv71_xult/examples/efc.rs index a9455f55..9e762b4b 100644 --- a/boards/atsamv71_xult/examples/efc.rs +++ b/boards/atsamv71_xult/examples/efc.rs @@ -7,10 +7,10 @@ use panic_rtt_target as _; #[rtic::app(device = hal::pac, peripherals = true, dispatchers = [UART0])] mod app { use atsamx7x_hal as hal; + use embedded_storage::nor_flash::NorFlash; + use embedded_storage::nor_flash::ReadNorFlash; use hal::efc::*; use rtt_target::{rprintln, rtt_init_print}; - use core::ptr; - #[shared] struct Shared {} @@ -22,42 +22,42 @@ mod app { fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) { rtt_init_print!(); let efc = ctx.device.EFC; - let wdt = ctx.device.WDT; - wdt.mr.modify(|_, w| w.wddis().set_bit()); rprintln!("0x{:x}", efc.eefc_fsr.read().bits()); rprintln!("0x{:x}", efc.eefc_fmr.read().bits()); - let flash_sectors = Efc::new(efc, VddioLevel::V3).sectors; - let sector0 = flash_sectors.sector0; + let mut efc = Efc::new(efc, VddioLevel::V3); + let wdt = ctx.device.WDT; + wdt.mr.modify(|_, w| w.wddis().set_bit()); + let mut a: [u8; 4] = [0; 4]; for i in 0..32768 { - rprintln!("Word 0x{:x}: 0x{:x}", i, sector0.read_word(i).unwrap()); + efc.read(i * 4, &mut a).unwrap(); + let a_int: u32 = u32::from_be_bytes(a); + rprintln!("Word 0x{:x}: 0x{:x}", i, a_int); } - let dead_beef: [usize; 128] = [0xdeadbeef; 128]; - let sector8 = flash_sectors.sector8; + let array: [u8; 512] = [0xad; 512]; for _j in 0..10 { - unsafe { sector8.write_page(0, &dead_beef).unwrap() }; - unsafe { sector8.write_page(1, &dead_beef).unwrap() }; - unsafe { sector8.write_page(2, &dead_beef).unwrap() }; - unsafe { sector8.write_page(3, &dead_beef).unwrap() }; + efc.write(SECTOR_SIZE as u32 * 8, &array).unwrap(); + efc.write(SECTOR_SIZE as u32 * 8 + PAGE_SIZE as u32, &array) + .unwrap(); + efc.write(SECTOR_SIZE as u32 * 8 + 2 * PAGE_SIZE as u32, &array) + .unwrap(); + efc.write(SECTOR_SIZE as u32 * 8 + 3 * PAGE_SIZE as u32, &array) + .unwrap(); for i in 8..12 { - rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); + efc.read(SECTOR_SIZE as u32 * 8 + i * 4, &mut a).unwrap(); + let a_int: u32 = u32::from_be_bytes(a); + rprintln!("Word 0x{:x}: 0x{:x}", i, a_int); } rprintln!("Erasing Flash Sector..."); - unsafe { sector8.erase_sector().unwrap() }; + efc.erase(SECTOR_SIZE as u32 * 8, SECTOR_SIZE as u32 * 9) + .unwrap(); rprintln!("Flash Sector Erased"); for i in 8..12 { - rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); + efc.read(SECTOR_SIZE as u32 * 8 + i * 4, &mut a).unwrap(); + let a_int: u32 = u32::from_be_bytes(a); + rprintln!("Word 0x{:x}: 0x{:x}", i, a_int); } } - unsafe { sector8.write_page(0, &dead_beef).unwrap() }; - unsafe { sector8.write_page(1, &dead_beef).unwrap() }; - unsafe { sector8.write_page(2, &dead_beef).unwrap() }; - unsafe { sector8.write_page(3, &dead_beef).unwrap() }; - for i in 8..12 { - rprintln!("Word 0x{:x}: 0x{:x}", i, sector8.read_word(i).unwrap()); - } - unsafe { sector8.write_word(0xbeefbeef, 10).unwrap() }; - rprintln!("0x{:x}", sector8.read_word(10).unwrap()); (Shared {}, Local {}, init::Monotonics()) diff --git a/hal/Cargo.toml b/hal/Cargo.toml index 0a76e123..b4a10604 100644 --- a/hal/Cargo.toml +++ b/hal/Cargo.toml @@ -39,6 +39,7 @@ void = { version = "1", default-features = false } strum = { version = "0.24.1", default-features = false, features = ["derive"]} cfg-if = "1" mcan-core = { version = "0.2", optional = true } +embedded-storage = "0.3" atsame70j19b = { version = "0.25.0", path = "../pac/atsame70j19b", optional = true } atsame70j20b = { version = "0.25.0", path = "../pac/atsame70j20b", optional = true } diff --git a/hal/src/efc.rs b/hal/src/efc.rs index d6202d2a..dc31e6b6 100644 --- a/hal/src/efc.rs +++ b/hal/src/efc.rs @@ -13,7 +13,8 @@ The wait states need to be reconfigured to allow for correct operation at higher use crate::clocks::{ClockError, Megahertz}; use crate::pac::{efc, EFC}; -use core::ptr; +use core::slice; +use embedded_storage::nor_flash::*; /// The voltage which drives the MCU. /// @@ -26,82 +27,53 @@ pub enum VddioLevel { V1, } -/// Set of [`Sector`]s for device Flash Memory. -#[allow(missing_docs)] -pub struct Sectors { - pub sector0: Sector<0>, - pub sector1: Sector<1>, - pub sector2: Sector<2>, - pub sector3: Sector<3>, - #[cfg(not(feature = "flash-512K"))] - pub sector4: Sector<4>, - #[cfg(not(feature = "flash-512K"))] - pub sector5: Sector<5>, - #[cfg(not(feature = "flash-512K"))] - pub sector6: Sector<6>, - #[cfg(not(feature = "flash-512K"))] - pub sector7: Sector<7>, - #[cfg(feature = "flash-2M")] - pub sector8: Sector<8>, - #[cfg(feature = "flash-2M")] - pub sector9: Sector<9>, - #[cfg(feature = "flash-2M")] - pub sector10: Sector<10>, - #[cfg(feature = "flash-2M")] - pub sector11: Sector<11>, - #[cfg(feature = "flash-2M")] - pub sector12: Sector<12>, - #[cfg(feature = "flash-2M")] - pub sector13: Sector<13>, - #[cfg(feature = "flash-2M")] - pub sector14: Sector<14>, - #[cfg(feature = "flash-2M")] - pub sector15: Sector<15>, +/// The Base Address of the Flash Memory. +pub const BASE_ADDRESS: u32 = 0x00400000; +///The Capacity in bytes of the Flash Memory. +#[cfg(feature = "flash-2M")] +pub const CAPACITY: usize = 0x00200000; +#[cfg(feature = "flash-1M")] +pub const CAPACITY: usize = 0x00100000; +#[cfg(feature = "flash-512K")] +pub const CAPACITY: usize = 0x00080000; +/// The Size in bytes of a page in the Flash Memory. +pub const PAGE_SIZE: usize = 512; +/// The Size in bytes of a sector in the Flash Memory. +pub const SECTOR_SIZE: usize = 0x00020000; + +/// An iterator over the Flash Sectors. +struct SectorIterator { + index: u8, + number_of_sectors: u8, +} + +/// A struct representing a Sector in Flash Memory. +#[derive(Clone, Copy)] +struct Sector { + n: u8, } -impl Sectors { - /// Create the set of all Flash Sector [`Token`]s. - fn new() -> Self { - Self { - sector0: Sector::new(), - sector1: Sector::new(), - sector2: Sector::new(), - sector3: Sector::new(), - #[cfg(not(feature = "flash-512K"))] - sector4: Sector::new(), - #[cfg(not(feature = "flash-512K"))] - sector5: Sector::new(), - #[cfg(not(feature = "flash-512K"))] - sector6: Sector::new(), - #[cfg(not(feature = "flash-512K"))] - sector7: Sector::new(), - #[cfg(feature = "flash-2M")] - sector8: Sector::new(), - #[cfg(feature = "flash-2M")] - sector9: Sector::new(), - #[cfg(feature = "flash-2M")] - sector10: Sector::new(), - #[cfg(feature = "flash-2M")] - sector11: Sector::new(), - #[cfg(feature = "flash-2M")] - sector12: Sector::new(), - #[cfg(feature = "flash-2M")] - sector13: Sector::new(), - #[cfg(feature = "flash-2M")] - sector14: Sector::new(), - #[cfg(feature = "flash-2M")] - sector15: Sector::new() +impl Iterator for SectorIterator { + type Item = Sector; + + fn next(&mut self) -> Option { + self.index += 1; + + if self.index < self.number_of_sectors { + Some(Sector { n: self.index }) + } else { + None } } } -/// Struct representing a sector of Flash Memory -pub struct Sector {} -/// Error Enum, Big WIP on this one. +/// Flash Memory Read/Write/Erase Errors. #[derive(Debug, Copy, Clone)] pub enum Error { - /// Access Outside Of the Flash Sector - SectorRangeError, + /// The arguments are not properly aligned. + NotAligned, + /// The arguments are out of bounds. + OutOfBounds, /// Attempted to execute a command when eefc is busy FlashBusyError, /// An invalid Command and/or a bad keyword was/were written in EEFC_FMR @@ -119,6 +91,18 @@ pub enum Error { UniqueEccErrorMsb, /// UniqueEccErrorLsb UniqueEccErrorLsb, + /// OtherError + OtherError, +} + +impl NorFlashError for Error { + fn kind(&self) -> NorFlashErrorKind { + match self { + Error::NotAligned => NorFlashErrorKind::NotAligned, + Error::OutOfBounds => NorFlashErrorKind::OutOfBounds, + _ => NorFlashErrorKind::Other, + } + } } impl From for Error { @@ -143,29 +127,26 @@ impl From for Error { } } -/// Token Representing a sector in flash memory -impl Sector { - /// Read a single 32 bit word from a flash sector. - pub fn read_word(&self, offset: usize) -> Result { - // Check that offset is still within range of the sector - if offset > 32767 { - return Err(Error::SectorRangeError); +impl From for Error { + fn from(e: NorFlashErrorKind) -> Error { + match e { + NorFlashErrorKind::NotAligned => Error::NotAligned, + NorFlashErrorKind::OutOfBounds => Error::OutOfBounds, + _ => Error::OtherError, } - Ok(unsafe { ptr::read_volatile(self.addr().offset(offset.try_into().unwrap())) }) } +} +impl Sector { /// Erase the entire sector. - /// # Safety - /// - /// Do not erase a flash sector where you are exectuing code. - pub unsafe fn erase_sector(&self) -> Result<(), Error> { + fn erase_sector(&self) -> Result<(), Error> { if self.efc().eefc_fsr.read().frdy().bit_is_clear() { return Err(Error::FlashBusyError); } self.efc().eefc_fcr.write(|w| { w.fkey().passwd(); w.fcmd().es(); - w.farg().bits((256_u16 * (N as u16)) as u16); + unsafe { w.farg().bits((256_u16 * (self.n as u16)) as u16) }; w }); loop { @@ -182,52 +163,23 @@ impl Sector { } /// Write page to flash memory. - /// # Safety - /// - /// Do not erase a flash sector where you are exectuing code. - pub unsafe fn write_page(&self, page: u8, data: &[usize; 128]) -> Result<(), Error> { - if self.efc().eefc_fsr.read().frdy().bit_is_clear() { - return Err(Error::FlashBusyError); - } - self.addr() - .offset(((page as u16) * 512) as isize) - .copy_from(data.as_ptr(), 128); - - self.efc().eefc_fcr.write(|w| { - w.fkey().passwd(); - w.fcmd().wp(); - w.farg().bits(256_u16 * (N as u16) + (page as u16)); - w - }); - loop { - let status = self.efc().eefc_fsr.read(); - // Wait until frdy is set - if status.bits() == 0x00000001 { - return Ok(()); - } - // If an error is detected, return - else if status.bits() != 0x00000000 { - return Err(status.bits().into()); - } - } - } - - /// Write single 32-bit word to flash memory. - /// # Safety - /// - /// Do not write to a flash sector where you are executing code. - pub unsafe fn write_word(&self, word: usize, offset: u16) -> Result<(), Error> { - if offset > 32767 { - return Err(Error::SectorRangeError); + fn write_page(&self, page: u8, data: &[u8]) -> Result<(), Error> { + if data.len() != PAGE_SIZE { + return Err(Error::NotAligned); } if self.efc().eefc_fsr.read().frdy().bit_is_clear() { return Err(Error::FlashBusyError); } - self.addr().offset(offset as isize).write_volatile(word); + unsafe { + self.addr() + .add((page as usize) * PAGE_SIZE) + .copy_from(data.as_ptr(), PAGE_SIZE) + }; + self.efc().eefc_fcr.write(|w| { w.fkey().passwd(); w.fcmd().wp(); - w.farg().bits(256_u16 * (N as u16) + (offset / 128)); + unsafe { w.farg().bits(256_u16 * (self.n as u16) + (page as u16)) }; w }); loop { @@ -243,30 +195,30 @@ impl Sector { } } - fn new() -> Self { - Self {} + #[inline(always)] + fn addr(&self) -> *mut u8 { + (BASE_ADDRESS as usize + (self.n as usize) * SECTOR_SIZE) as *mut u8 } -} -trait RegisterAccess { #[inline(always)] - fn addr(&self) -> *mut usize { - (0x400000 + (N as usize) * 0x20000) as *mut usize + fn contains(&self, offset: u32) -> bool { + offset >= SECTOR_SIZE as u32 * self.n as u32 + && offset < SECTOR_SIZE as u32 * (self.n as u32 + 1) } +} +trait RegisterAccess { fn efc(&self) -> &efc::RegisterBlock { unsafe { &*EFC::ptr() } } } -impl RegisterAccess for Sector {} +impl RegisterAccess for Sector {} /// [`EFC`] abstraction. pub struct Efc { pub(crate) periph: EFC, vddio: VddioLevel, - /// struct representing the flash memory sectors. - pub sectors: Sectors, } impl Efc { @@ -278,13 +230,8 @@ impl Efc { w.wpen().clear_bit(); w }); - let sectors = Sectors::new(); - Self { - periph, - vddio, - sectors, - } + Self { periph, vddio } } /// Calculates and sets the lowest possible number of flash wait @@ -303,6 +250,95 @@ impl Efc { } } +trait Flash { + type SectorIterator; + fn len(&self) -> usize { + CAPACITY + } + fn address(&self) -> u32 { + BASE_ADDRESS + } + fn sectors() -> SectorIterator { + SectorIterator { + index: 0, + number_of_sectors: (CAPACITY / SECTOR_SIZE) as u8, + } + } +} + +impl Flash for Efc { + type SectorIterator = SectorIterator; +} + +impl ErrorType for Efc { + type Error = Error; +} + +impl ReadNorFlash for Efc { + const READ_SIZE: usize = 1; + + fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { + check_read(self, offset, bytes.len())?; + let offset = offset as usize; + let ptr = self.address() as *const _; + let capacity = self.capacity(); + let flash_slice = unsafe { slice::from_raw_parts(ptr, capacity) }; + bytes.copy_from_slice(&flash_slice[offset..offset + bytes.len()]); + Ok(()) + } + + fn capacity(&self) -> usize { + self.len() + } +} + +impl NorFlash for Efc { + const WRITE_SIZE: usize = PAGE_SIZE; + // NOTE: This number is the sector size, there is an option to erase by page as well, but the + // minimum/maximum erase size for that varies throughout the flash memory. + const ERASE_SIZE: usize = SECTOR_SIZE; + + fn erase(&mut self, offset: u32, to: u32) -> Result<(), Self::Error> { + check_erase(self, offset, to)?; + let mut offset = offset; + for sector in Self::sectors() { + if sector.contains(offset) { + sector.erase_sector()?; + offset += Self::ERASE_SIZE as u32; + } + if offset >= to { + break; + } + } + Ok(()) + } + + fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { + check_write(self, offset, bytes.len())?; + let mut offset = offset; + let mut bytes_written = 0; + for sector in Self::sectors() { + while sector.contains(offset) { + let sector_offset = sector.n as usize * SECTOR_SIZE; + let page = ((offset as usize - sector_offset) / Self::WRITE_SIZE) as u8; + sector.write_page( + page, + &bytes[bytes_written..(bytes_written + Self::WRITE_SIZE)], + )?; + bytes_written += Self::WRITE_SIZE; + offset += Self::WRITE_SIZE as u32; + if bytes_written >= bytes.len() { + break; + } + } + if bytes_written >= bytes.len() { + break; + } + } + Ok(()) + } +} + /// The number of flash wait states for a read operation. /// /// Note: The number of cycles a read takes is 1 + FWS. From 5fd4c3b34a73e5cbe77ce6ae7912a6e18035f4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6rtsell?= Date: Wed, 23 Aug 2023 16:07:32 +0200 Subject: [PATCH 4/8] Improve Readability of Write And Erase Methods Add Doc Comment To CAPACITY const --- hal/src/efc.rs | 161 +++++++++++++++++++++++++++++++------------------ 1 file changed, 101 insertions(+), 60 deletions(-) diff --git a/hal/src/efc.rs b/hal/src/efc.rs index dc31e6b6..53b02faf 100644 --- a/hal/src/efc.rs +++ b/hal/src/efc.rs @@ -31,39 +31,71 @@ pub enum VddioLevel { pub const BASE_ADDRESS: u32 = 0x00400000; ///The Capacity in bytes of the Flash Memory. #[cfg(feature = "flash-2M")] -pub const CAPACITY: usize = 0x00200000; +pub const CAPACITY: u32 = 0x00200000; +///The Capacity in bytes of the Flash Memory. #[cfg(feature = "flash-1M")] -pub const CAPACITY: usize = 0x00100000; +pub const CAPACITY: u32 = 0x00100000; +///The Capacity in bytes of the Flash Memory. #[cfg(feature = "flash-512K")] -pub const CAPACITY: usize = 0x00080000; +pub const CAPACITY: u32 = 0x00080000; /// The Size in bytes of a page in the Flash Memory. -pub const PAGE_SIZE: usize = 512; +pub const PAGE_SIZE: u32 = 512; /// The Size in bytes of a sector in the Flash Memory. -pub const SECTOR_SIZE: usize = 0x00020000; +pub const SECTOR_SIZE: u32 = 0x00020000; /// An iterator over the Flash Sectors. struct SectorIterator { - index: u8, - number_of_sectors: u8, + start_offset: u32, + end_offset: u32, } /// A struct representing a Sector in Flash Memory. #[derive(Clone, Copy)] struct Sector { - n: u8, + offset: u32, } impl Iterator for SectorIterator { type Item = Sector; fn next(&mut self) -> Option { - self.index += 1; + if self.start_offset >= self.end_offset { + return None; + } + let sector = Sector { + offset: self.start_offset, + }; + self.start_offset += SECTOR_SIZE; - if self.index < self.number_of_sectors { - Some(Sector { n: self.index }) - } else { - None + Some(sector) + } +} + +/// A struct representing a Page in Flash memory +#[derive(Clone, Copy)] +struct Page { + offset: u32, +} + +/// An iterator over the Flash Pages. +struct PageIterator { + start_offset: u32, + end_offset: u32, +} + +impl Iterator for PageIterator { + type Item = Page; + + fn next(&mut self) -> Option { + if self.start_offset >= self.end_offset { + return None; } + let page = Page { + offset: self.start_offset, + }; + self.start_offset += PAGE_SIZE; + + Some(page) } } @@ -146,7 +178,7 @@ impl Sector { self.efc().eefc_fcr.write(|w| { w.fkey().passwd(); w.fcmd().es(); - unsafe { w.farg().bits((256_u16 * (self.n as u16)) as u16) }; + unsafe { w.farg().bits(self.page_number()) }; w }); loop { @@ -162,24 +194,37 @@ impl Sector { } } + // #[inline(always)] fn addr(&self) -> *mut u8 { + // (BASE_ADDRESS + self.offset) as *mut u8 + // } + + #[inline(always)] + fn page_number(&self) -> u16 { + (self.offset / PAGE_SIZE) as u16 + } + + // #[inline(always)] + // fn contains(&self, offset: u32) -> bool { + // offset >= self.offset + // && offset < self.offset + SECTOR_SIZE + // } +} + +impl Page { /// Write page to flash memory. - fn write_page(&self, page: u8, data: &[u8]) -> Result<(), Error> { - if data.len() != PAGE_SIZE { + fn write_page(&self, data: &[u8]) -> Result<(), Error> { + if data.len() != PAGE_SIZE as usize { return Err(Error::NotAligned); } if self.efc().eefc_fsr.read().frdy().bit_is_clear() { return Err(Error::FlashBusyError); } - unsafe { - self.addr() - .add((page as usize) * PAGE_SIZE) - .copy_from(data.as_ptr(), PAGE_SIZE) - }; + unsafe { self.addr().copy_from(data.as_ptr(), PAGE_SIZE as usize) }; self.efc().eefc_fcr.write(|w| { w.fkey().passwd(); w.fcmd().wp(); - unsafe { w.farg().bits(256_u16 * (self.n as u16) + (page as u16)) }; + unsafe { w.farg().bits(self.page_number()) }; w }); loop { @@ -197,15 +242,20 @@ impl Sector { #[inline(always)] fn addr(&self) -> *mut u8 { - (BASE_ADDRESS as usize + (self.n as usize) * SECTOR_SIZE) as *mut u8 + (BASE_ADDRESS + self.offset) as *mut u8 } #[inline(always)] - fn contains(&self, offset: u32) -> bool { - offset >= SECTOR_SIZE as u32 * self.n as u32 - && offset < SECTOR_SIZE as u32 * (self.n as u32 + 1) + fn page_number(&self) -> u16 { + (self.offset / PAGE_SIZE) as u16 } + + // #[inline(always)] + // fn contains(&self, offset: u32) -> bool { + // offset >= self.offset + // && offset < self.offset + PAGE_SIZE as u32 + // } } trait RegisterAccess { @@ -215,6 +265,7 @@ trait RegisterAccess { } impl RegisterAccess for Sector {} +impl RegisterAccess for Page {} /// [`EFC`] abstraction. pub struct Efc { pub(crate) periph: EFC, @@ -252,22 +303,34 @@ impl Efc { trait Flash { type SectorIterator; - fn len(&self) -> usize { + type PageIterator; + + fn len(&self) -> u32 { CAPACITY } + fn address(&self) -> u32 { BASE_ADDRESS } - fn sectors() -> SectorIterator { + + fn sectors(start_offset: u32, end_offset: u32) -> SectorIterator { SectorIterator { - index: 0, - number_of_sectors: (CAPACITY / SECTOR_SIZE) as u8, + start_offset, + end_offset, + } + } + + fn pages(start_offset: u32, end_offset: u32) -> PageIterator { + PageIterator { + start_offset, + end_offset, } } } impl Flash for Efc { type SectorIterator = SectorIterator; + type PageIterator = PageIterator; } impl ErrorType for Efc { @@ -288,52 +351,30 @@ impl ReadNorFlash for Efc { } fn capacity(&self) -> usize { - self.len() + self.len() as usize } } impl NorFlash for Efc { - const WRITE_SIZE: usize = PAGE_SIZE; + const WRITE_SIZE: usize = PAGE_SIZE as usize; // NOTE: This number is the sector size, there is an option to erase by page as well, but the // minimum/maximum erase size for that varies throughout the flash memory. - const ERASE_SIZE: usize = SECTOR_SIZE; + const ERASE_SIZE: usize = SECTOR_SIZE as usize; fn erase(&mut self, offset: u32, to: u32) -> Result<(), Self::Error> { check_erase(self, offset, to)?; - let mut offset = offset; - for sector in Self::sectors() { - if sector.contains(offset) { - sector.erase_sector()?; - offset += Self::ERASE_SIZE as u32; - } - if offset >= to { - break; - } + for sector in Self::sectors(offset, to) { + sector.erase_sector()?; } Ok(()) } fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { check_write(self, offset, bytes.len())?; - let mut offset = offset; let mut bytes_written = 0; - for sector in Self::sectors() { - while sector.contains(offset) { - let sector_offset = sector.n as usize * SECTOR_SIZE; - let page = ((offset as usize - sector_offset) / Self::WRITE_SIZE) as u8; - sector.write_page( - page, - &bytes[bytes_written..(bytes_written + Self::WRITE_SIZE)], - )?; - bytes_written += Self::WRITE_SIZE; - offset += Self::WRITE_SIZE as u32; - if bytes_written >= bytes.len() { - break; - } - } - if bytes_written >= bytes.len() { - break; - } + for page in Self::pages(offset, offset + bytes.len() as u32) { + page.write_page(&bytes[bytes_written..(bytes_written + Self::WRITE_SIZE)])?; + bytes_written += Self::WRITE_SIZE; } Ok(()) } From 6d5e397b2c7917a1d39b26f264b51c3c4f35fd3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6rtsell?= Date: Thu, 24 Aug 2023 13:33:38 +0200 Subject: [PATCH 5/8] `fmt` --- boards/atsamv71_xult/examples/efc.rs | 1 - hal/src/efc.rs | 2 -- 2 files changed, 3 deletions(-) diff --git a/boards/atsamv71_xult/examples/efc.rs b/boards/atsamv71_xult/examples/efc.rs index 9e762b4b..03973ed3 100644 --- a/boards/atsamv71_xult/examples/efc.rs +++ b/boards/atsamv71_xult/examples/efc.rs @@ -59,7 +59,6 @@ mod app { } } - (Shared {}, Local {}, init::Monotonics()) } } diff --git a/hal/src/efc.rs b/hal/src/efc.rs index 53b02faf..b1dfeebe 100644 --- a/hal/src/efc.rs +++ b/hal/src/efc.rs @@ -245,7 +245,6 @@ impl Page { (BASE_ADDRESS + self.offset) as *mut u8 } - #[inline(always)] fn page_number(&self) -> u16 { (self.offset / PAGE_SIZE) as u16 @@ -440,4 +439,3 @@ impl FlashWaitStates { } } } - From 27426f3263886d5e68dcdf72cdfb8ee8eb568bf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6rtsell?= Date: Thu, 24 Aug 2023 13:43:37 +0200 Subject: [PATCH 6/8] Revert Changes Made To Examples Unrelated To PR --- boards/atsamv71_xult/examples/blinky.rs | 27 +++++++++------------ boards/atsamv71_xult/examples/blinky_irq.rs | 2 +- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/boards/atsamv71_xult/examples/blinky.rs b/boards/atsamv71_xult/examples/blinky.rs index b460860e..c98e55ff 100644 --- a/boards/atsamv71_xult/examples/blinky.rs +++ b/boards/atsamv71_xult/examples/blinky.rs @@ -3,19 +3,19 @@ #![no_main] use panic_rtt_target as _; -// use panic_halt as _; + #[rtic::app(device = hal::pac, peripherals = true, dispatchers = [UART0])] mod app { use atsamx7x_hal as hal; use hal::clocks::*; - use hal::efc::{Efc, VddioLevel}; + use hal::efc::*; use hal::ehal::digital::v2::ToggleableOutputPin; use hal::pio::*; use hal::rtt::*; use rtt_target::{rprintln, rtt_init_print}; - // #[monotonic(binds = RTT, default = true)] - // type MyMono = Mono<8192>; + #[monotonic(binds = RTT, default = true)] + type MyMono = Mono<8192>; #[shared] struct Shared {} @@ -28,7 +28,6 @@ mod app { #[init] fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) { rtt_init_print!(); - rprintln!("Init"); let clocks = Tokens::new( (ctx.device.PMC, ctx.device.SUPC, ctx.device.UTMI), @@ -55,21 +54,17 @@ mod app { ); let led = banka.pa23.into_output(true); - // let mono = Rtt::new_8192Hz(ctx.device.RTT, &slck).into_monotonic(); + let mono = Rtt::new_8192Hz(ctx.device.RTT, &slck).into_monotonic(); - // toggle_led::spawn().unwrap(); + toggle_led::spawn().unwrap(); - (Shared {}, Local { led }, init::Monotonics()) + (Shared {}, Local { led }, init::Monotonics(mono)) } - #[idle(local = [led])] - fn idle(ctx: idle::Context) -> ! { - rprintln!("Idle"); + #[task(local = [led])] + fn toggle_led(ctx: toggle_led::Context) { ctx.local.led.toggle().unwrap(); - loop { - rprintln!("Loop"); - ctx.local.led.toggle().unwrap(); - cortex_m::asm::delay(2000000); - } + rprintln!("LED0 toggled"); + toggle_led::spawn_after(1.secs()).unwrap(); } } diff --git a/boards/atsamv71_xult/examples/blinky_irq.rs b/boards/atsamv71_xult/examples/blinky_irq.rs index bdf6e803..687af9c1 100644 --- a/boards/atsamv71_xult/examples/blinky_irq.rs +++ b/boards/atsamv71_xult/examples/blinky_irq.rs @@ -9,7 +9,7 @@ use panic_rtt_target as _; mod app { use atsamx7x_hal as hal; use hal::clocks::*; - use hal::efc::{Efc, VddioLevel}; + use hal::efc::*; use hal::ehal::digital::v2::ToggleableOutputPin; use hal::ehal::timer::CountDown; use hal::pio::*; From 8732209611655b3aafb9406ca65d0dae760ffc6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6rtsell?= Date: Fri, 25 Aug 2023 09:49:51 +0200 Subject: [PATCH 7/8] Improve Top Level Efc Documentation --- hal/src/efc.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/hal/src/efc.rs b/hal/src/efc.rs index b1dfeebe..ee61317e 100644 --- a/hal/src/efc.rs +++ b/hal/src/efc.rs @@ -3,12 +3,37 @@ Flash controller configuration --- The Enhanced Embedded Flash Controller peripheral (EFC) or (EEFC) provides the interface of the Flash block with the 32-bit internal bus. - Two functions of the EFC are exposed in this HAL, the ability to set wait states, and the ability to reconfigure the flash memory. - The wait states need to be reconfigured to allow for correct operation at higher clock frequencies and is normally handled by the [clocks](crate::clocks) module. +The flash memory can be modified using the commands in Table 22-1. +Out of these commands only the Write Page and Erase Sector commands are currently supported by the HAL. +Write Page writes a page of 512 bytes, Erase Sector erases a sector a sector of 128KB. + +That is, your writes need to be 512 byte aligned, because pages are 512 byte aligned, and your erases need to be 128KB aligned, because sectors are 128KB aligned. +# Example usage + +```no_run +# use atsamx7x_hal as hal; +use embedded_storage::nor_flash::NorFlash; +use embedded_storage::nor_flash::ReadNorFlash; +# use hal::efc::*; + +let efc = ctx.device.EFC; +let mut efc = Efc::new(efc, VddioLevel::V3); + +let mut a: [u8; 128] = [0; 128]; +// Read the first 128 bytes from the flash memory +efc.read(0, &mut a).unwrap(); + +let b: [u8; 512] = [0x00; 512]; +// Write 0x00 to the first page of the second sector +efc.write(SECTOR_SIZE, &b).unwrap(); + +// erase the third sector +efc.erase(2*SECTOR_SIZE, SECTOR_SIZE*3).unwrap(); +``` */ use crate::clocks::{ClockError, Megahertz}; From aa32162e7694b4899703f4fb2a4efee08e190cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6rtsell?= Date: Fri, 25 Aug 2023 12:50:04 +0200 Subject: [PATCH 8/8] Fix efc Doc Example --- hal/src/efc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hal/src/efc.rs b/hal/src/efc.rs index ee61317e..048d4bef 100644 --- a/hal/src/efc.rs +++ b/hal/src/efc.rs @@ -18,9 +18,9 @@ That is, your writes need to be 512 byte aligned, because pages are 512 byte ali use embedded_storage::nor_flash::NorFlash; use embedded_storage::nor_flash::ReadNorFlash; # use hal::efc::*; +# let pac = hal::pac::Peripherals::take().unwrap(); -let efc = ctx.device.EFC; -let mut efc = Efc::new(efc, VddioLevel::V3); +let mut efc = Efc::new(pac.EFC, VddioLevel::V3); let mut a: [u8; 128] = [0; 128]; // Read the first 128 bytes from the flash memory