diff --git a/src/boot/mod.rs b/src/boot/mod.rs index e9cc090..b770311 100644 --- a/src/boot/mod.rs +++ b/src/boot/mod.rs @@ -1,8 +1,7 @@ use crate::{ hardware::processor::Processor, hardware::{Bank, Config}, - state::{ExchangeProgress, ExchangeStep, State, Update, UpdateError}, - swap::{MemoryError, Swap}, + state::{Exchange, ExchangeProgress, ExchangeStep, MemoryError, State, Update, UpdateError}, }; use embedded_storage::Storage; @@ -15,47 +14,47 @@ use defmt::Format; /// Use this from your bootloader application and call boot() to do the magic, reading the current /// state via the State type and then jumping to the new image using the Jumper specified pub struct MoonbootBoot< - InternalMemory: Storage, - HardwareState: State, - CPU: Processor, // TODO: Wrap these into a context struct like rubble? - PageSwap: Swap, + STORAGE: Storage, + STATE: State, + PROCESSOR: Processor, // TODO: Wrap these into a context struct like rubble? + EXCHANGE: Exchange, const INTERNAL_PAGE_SIZE: usize, > { config: Config, - internal_memory: InternalMemory, - state: HardwareState, - processor: CPU, - swap: PageSwap, + storage: STORAGE, + state: STATE, + processor: PROCESSOR, + exchange: EXCHANGE, } impl< - InternalMemory: Storage, - HardwareState: State, - CPU: Processor, - PageSwap: Swap, + STORAGE: Storage, + STATE: State, + PROCESSOR: Processor, + EXCHANGE: Exchange, const INTERNAL_PAGE_SIZE: usize, - > MoonbootBoot + > MoonbootBoot { /// create a new instance of the bootloader pub fn new( config: Config, - internal_memory: InternalMemory, - state: HardwareState, - processor: CPU, - swap: PageSwap, - ) -> MoonbootBoot { + storage: STORAGE, + state: STATE, + processor: PROCESSOR, + exchange: EXCHANGE, + ) -> MoonbootBoot { Self { config, - internal_memory, + storage, state, processor, - swap, + exchange, } } /// Destroy this instance of the bootloader and return access to the hardware peripheral - pub fn destroy(self) -> (InternalMemory, HardwareState, CPU) { - (self.internal_memory, self.state, self.processor) + pub fn destroy(self) -> (STORAGE, STATE, PROCESSOR) { + (self.storage, self.state, self.processor) } /// Execute the update and boot logic of the bootloader @@ -124,9 +123,9 @@ impl< ); let exchange_result = self - .swap - .exchange::( - &mut self.internal_memory, + .exchange + .exchange::( + &mut self.storage, &mut self.state, progress, ); @@ -165,7 +164,7 @@ impl< old.location, old.size / 1024, new.location, - new.size / 1024, + new.size / 1024 ); // Try to exchange the firmware images @@ -195,9 +194,9 @@ impl< } fn exchange_banks(&mut self, a: Bank, b: Bank) -> Result<(), MemoryError> { - self.swap - .exchange::( - &mut self.internal_memory, + self.exchange + .exchange::( + &mut self.storage, &mut self.state, ExchangeProgress { a, diff --git a/src/hardware/processor.rs b/src/hardware/processor.rs index b447c80..33be20a 100644 --- a/src/hardware/processor.rs +++ b/src/hardware/processor.rs @@ -29,7 +29,7 @@ pub mod cortex_m { fn do_jump(&mut self, address: super::Address) -> ! { unsafe { // Set Vector Table to new vector table (unsafe but okay here) - (*cortex_m::peripheral::SCB::ptr()).vtor.write(address); + (*cortex_m::peripheral::SCB::PTR).vtor.write(address); cortex_m::asm::bootload(address as *const u32); } @@ -40,4 +40,3 @@ pub mod cortex_m { } } } - diff --git a/src/lib.rs b/src/lib.rs index 145e998..759729c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,8 +24,6 @@ pub use manager::MoonbootManager; pub mod hardware; /// Shared state management between firmware and bootloader pub mod state; -/// Abstractions on the method of flash page swapping. -pub mod swap; pub use embedded_storage; diff --git a/src/state.rs b/src/state/mod.rs similarity index 65% rename from src/state.rs rename to src/state/mod.rs index 01fed21..95f50a9 100644 --- a/src/state.rs +++ b/src/state/mod.rs @@ -1,10 +1,37 @@ +#[cfg(feature = "ram-state")] +pub mod ram; + +#[cfg(feature = "scratch-state")] +pub mod scratch; + +use embedded_storage::Storage; + +/// Error occured during memory access +#[cfg_attr(feature = "use-defmt", derive(Format))] +#[derive(Debug)] +pub enum MemoryError { + BankSizeNotEqual, + BankSizeZero, + ReadFailure, + WriteFailure, +} + +/// Abstraction for the exchange operation of the current state. +pub trait Exchange { + fn exchange( + &mut self, + internal_memory: &mut STORAGE, + state: &mut STATE, + progress: ExchangeProgress, + ) -> Result<(), MemoryError>; +} + use crate::hardware::Bank; -use crate::log; use crc::{Crc, CRC_32_CKSUM}; #[cfg(feature = "defmt")] use defmt::Format; -#[cfg(feature = "ram-state")] +#[cfg(any(feature = "ram-state", feature = "scratch-state"))] use desse::{Desse, DesseSized}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -14,7 +41,10 @@ use serde::{Deserialize, Serialize}; // exchanged via software updates easily #[cfg_attr(feature = "use-defmt", derive(Format))] #[cfg_attr(feature = "derive", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))] +#[cfg_attr( + any(feature = "ram-state", feature = "scratch-state"), + derive(Desse, DesseSized) +)] #[derive(Debug, PartialEq, Eq)] pub enum Update { // No update requested, just jump to the application @@ -33,7 +63,10 @@ pub enum Update { #[cfg_attr(feature = "use-defmt", derive(Format))] #[cfg_attr(feature = "derive", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))] +#[cfg_attr( + any(feature = "ram-state", feature = "scratch-state"), + derive(Desse, DesseSized) +)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] /// Errors that can occur during update pub enum UpdateError { @@ -50,7 +83,10 @@ pub enum UpdateError { /// Upcoming operation of the exchange process for a given page index. #[cfg_attr(feature = "use-defmt", derive(Format))] #[cfg_attr(feature = "derive", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))] +#[cfg_attr( + any(feature = "ram-state", feature = "scratch-state"), + derive(Desse, DesseSized) +)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ExchangeStep { /// Copy page A to the scratch page. @@ -64,7 +100,10 @@ pub enum ExchangeStep { /// Store the progress of the current exchange operation #[cfg_attr(feature = "use-defmt", derive(Format))] #[cfg_attr(feature = "derive", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))] +#[cfg_attr( + any(feature = "ram-state", feature = "scratch-state"), + derive(Desse, DesseSized) +)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct ExchangeProgress { /// Bank the update is coming from @@ -82,7 +121,10 @@ pub struct ExchangeProgress { /// Struct used to store the state of the bootloader situation in NVM #[cfg_attr(feature = "use-defmt", derive(Format))] #[cfg_attr(feature = "derive", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "ram-state", derive(Desse, DesseSized))] +#[cfg_attr( + any(feature = "ram-state", feature = "scratch-state"), + derive(Desse, DesseSized) +)] #[derive(Debug)] pub struct MoonbootState { /// If set Request, an Update is requested. This will exchange the two images, set the update @@ -112,63 +154,3 @@ const CRC: Crc = Crc::::new(&CRC_32_CKSUM); fn checksum(bytes: &[u8]) -> StateCrcType { CRC.checksum(bytes) } - -/// State stored in the RAM -/// TODO: Move to hardware folder together with state trait? -#[cfg(feature = "ram-state")] -pub mod ram { - use super::*; - - /// State read and written to RAM. This assumes the device is never powered off / the ram is never - /// reset! - pub struct RamState; - - extern "C" { - static mut _moonboot_state_crc_start: StateCrcType; - static mut _moonboot_state_data_start: [u8; STATE_SERIALIZED_MAX_SIZE]; - // TODO: Move these as normal variables to linker sections via #[link] macro? - } - - impl State for RamState { - fn read(&mut self) -> MoonbootState { - let crc = unsafe { _moonboot_state_crc_start }; - - log::info!( - "Reading data with len: {}, CRC: {}", - STATE_SERIALIZED_MAX_SIZE, - crc - ); - - let checksum = checksum(unsafe { &_moonboot_state_data_start }); - if crc == checksum { - let data = MoonbootState::deserialize_from(unsafe { &_moonboot_state_data_start }); - log::trace!("CRC Match! {}: {:?}", crc, data); - return data; - } else { - log::trace!("CRC Mismatch! {} vs {}", crc, checksum); - } - - MoonbootState { - update: Update::None, - } - } - - fn write(&mut self, data: &MoonbootState) -> Result<(), ()> { - log::trace!("Writing data {:?}", data); - - unsafe { _moonboot_state_data_start = data.serialize() }; - log::trace!("Written data: {:?}", unsafe { &_moonboot_state_data_start }); - - unsafe { - _moonboot_state_crc_start = checksum(&_moonboot_state_data_start); - } - log::info!( - "Written len: {}, checksum: {}", - STATE_SERIALIZED_MAX_SIZE, - unsafe { _moonboot_state_crc_start } - ); - - Ok(()) - } - } -} diff --git a/src/swap/ram.rs b/src/state/ram.rs similarity index 68% rename from src/swap/ram.rs rename to src/state/ram.rs index 2726291..1c11505 100644 --- a/src/swap/ram.rs +++ b/src/state/ram.rs @@ -1,15 +1,63 @@ use embedded_storage::Storage; -use crate::{ - log, - state::{ExchangeProgress, State, Update}, - swap::{MemoryError, Swap}, - Address, -}; +use crate::{log, Address}; -pub struct Ram; +use super::*; -impl Swap for Ram { +/// State read and written to RAM. This assumes the device is never powered off / the ram is never +/// reset! +pub struct RamState; + +extern "C" { + static mut _moonboot_state_crc_start: StateCrcType; + static mut _moonboot_state_data_start: [u8; STATE_SERIALIZED_MAX_SIZE]; + // TODO: Move these as normal variables to linker sections via #[link] macro? +} + +impl State for RamState { + fn read(&mut self) -> MoonbootState { + let crc = unsafe { _moonboot_state_crc_start }; + + log::info!( + "Reading data with len: {}, CRC: {}", + STATE_SERIALIZED_MAX_SIZE, + crc + ); + + let checksum = checksum(unsafe { &_moonboot_state_data_start }); + if crc == checksum { + let data = MoonbootState::deserialize_from(unsafe { &_moonboot_state_data_start }); + log::trace!("CRC Match! {}: {:?}", crc, data); + return data; + } else { + log::trace!("CRC Mismatch! {} vs {}", crc, checksum); + } + + MoonbootState { + update: Update::None, + } + } + + fn write(&mut self, data: &MoonbootState) -> Result<(), ()> { + log::trace!("Writing data {:?}", data); + + unsafe { _moonboot_state_data_start = data.serialize() }; + log::trace!("Written data: {:?}", unsafe { &_moonboot_state_data_start }); + + unsafe { + _moonboot_state_crc_start = checksum(&_moonboot_state_data_start); + } + log::info!( + "Written len: {}, checksum: {}", + STATE_SERIALIZED_MAX_SIZE, + unsafe { _moonboot_state_crc_start } + ); + + Ok(()) + } +} + +impl Exchange for RamState { fn exchange( &mut self, internal_memory: &mut InternalMemory, diff --git a/src/swap/scratch.rs b/src/state/scratch.rs similarity index 100% rename from src/swap/scratch.rs rename to src/state/scratch.rs diff --git a/src/swap/mod.rs b/src/swap/mod.rs deleted file mode 100644 index 477c56f..0000000 --- a/src/swap/mod.rs +++ /dev/null @@ -1,25 +0,0 @@ -pub mod ram; -pub mod scratch; - -use embedded_storage::Storage; - -use crate::state::{ExchangeProgress, State}; - -/// Error occured during memory access -#[cfg_attr(feature = "use-defmt", derive(Format))] -#[derive(Debug)] -pub enum MemoryError { - BankSizeNotEqual, - BankSizeZero, - ReadFailure, - WriteFailure, -} - -pub trait Swap { - fn exchange( - &mut self, - internal_memory: &mut InternalMemory, - state: &mut HardwareState, - exchange: ExchangeProgress, - ) -> Result<(), MemoryError>; -}