mirror of
https://github.com/jhbruhn/moonboot.git
synced 2025-03-15 01:55:50 +00:00
Change scratch to use a bank defined in config
This commit is contained in:
parent
40f93525b7
commit
a301aaa9ea
8 changed files with 34 additions and 11 deletions
|
@ -113,6 +113,7 @@ impl<CONTEXT: Context, const INTERNAL_PAGE_SIZE: usize> MoonbootBoot<CONTEXT, IN
|
||||||
);
|
);
|
||||||
|
|
||||||
let exchange_result = self.exchange.exchange::<INTERNAL_PAGE_SIZE>(
|
let exchange_result = self.exchange.exchange::<INTERNAL_PAGE_SIZE>(
|
||||||
|
&self.config,
|
||||||
&mut self.storage,
|
&mut self.storage,
|
||||||
&mut self.state,
|
&mut self.state,
|
||||||
progress,
|
progress,
|
||||||
|
@ -157,6 +158,7 @@ impl<CONTEXT: Context, const INTERNAL_PAGE_SIZE: usize> MoonbootBoot<CONTEXT, IN
|
||||||
|
|
||||||
// Try to exchange the firmware images
|
// Try to exchange the firmware images
|
||||||
let exchange_result = self.exchange.exchange::<INTERNAL_PAGE_SIZE>(
|
let exchange_result = self.exchange.exchange::<INTERNAL_PAGE_SIZE>(
|
||||||
|
&self.config,
|
||||||
&mut self.storage,
|
&mut self.storage,
|
||||||
&mut self.state,
|
&mut self.state,
|
||||||
ExchangeProgress {
|
ExchangeProgress {
|
||||||
|
|
|
@ -2,7 +2,10 @@ pub mod ram;
|
||||||
|
|
||||||
pub mod scratch;
|
pub mod scratch;
|
||||||
|
|
||||||
use crate::state::{ExchangeProgress, State};
|
use crate::{
|
||||||
|
hardware::Config,
|
||||||
|
state::{ExchangeProgress, State},
|
||||||
|
};
|
||||||
use embedded_storage::Storage;
|
use embedded_storage::Storage;
|
||||||
|
|
||||||
/// Abstraction for the exchange operation of the current state.
|
/// Abstraction for the exchange operation of the current state.
|
||||||
|
@ -11,6 +14,7 @@ pub trait Exchange<STORAGE: Storage, STATE: State> {
|
||||||
|
|
||||||
fn exchange<const INTERNAL_PAGE_SIZE: usize>(
|
fn exchange<const INTERNAL_PAGE_SIZE: usize>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
config: &Config,
|
||||||
storage: &mut STORAGE,
|
storage: &mut STORAGE,
|
||||||
state: &mut STATE,
|
state: &mut STATE,
|
||||||
progress: ExchangeProgress,
|
progress: ExchangeProgress,
|
||||||
|
|
|
@ -2,6 +2,7 @@ use embedded_storage::Storage;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
exchange::Exchange,
|
exchange::Exchange,
|
||||||
|
hardware::Config,
|
||||||
log,
|
log,
|
||||||
state::{ExchangeProgress, State, Update},
|
state::{ExchangeProgress, State, Update},
|
||||||
Address,
|
Address,
|
||||||
|
@ -36,6 +37,7 @@ where
|
||||||
|
|
||||||
fn exchange<const INTERNAL_PAGE_SIZE: usize>(
|
fn exchange<const INTERNAL_PAGE_SIZE: usize>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_config: &Config,
|
||||||
storage: &mut STORAGE,
|
storage: &mut STORAGE,
|
||||||
state: &mut STATE,
|
state: &mut STATE,
|
||||||
progress: ExchangeProgress,
|
progress: ExchangeProgress,
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
use core::{fmt::Debug, ops::Range};
|
use core::fmt::Debug;
|
||||||
|
|
||||||
use embedded_storage::Storage;
|
use embedded_storage::Storage;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
exchange::Exchange,
|
exchange::Exchange,
|
||||||
|
hardware::Config,
|
||||||
log,
|
log,
|
||||||
state::{ExchangeProgress, ExchangeStep, State, Update},
|
state::{ExchangeProgress, ExchangeStep, State, Update},
|
||||||
Address,
|
Address,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Scratch<'a> {
|
pub struct Scratch;
|
||||||
pub pages: &'a [Range<Address>],
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ExchangeError<STORAGE, STATE> {
|
pub enum ExchangeError<STORAGE, STATE> {
|
||||||
Storage(STORAGE),
|
Storage(STORAGE),
|
||||||
State(STATE),
|
State(STATE),
|
||||||
|
ScratchInsufficient,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<STORAGE, STATE> Debug for ExchangeError<STORAGE, STATE>
|
impl<STORAGE, STATE> Debug for ExchangeError<STORAGE, STATE>
|
||||||
|
@ -27,11 +27,12 @@ where
|
||||||
match self {
|
match self {
|
||||||
Self::Storage(arg0) => f.debug_tuple("Storage").field(arg0).finish(),
|
Self::Storage(arg0) => f.debug_tuple("Storage").field(arg0).finish(),
|
||||||
Self::State(arg0) => f.debug_tuple("State").field(arg0).finish(),
|
Self::State(arg0) => f.debug_tuple("State").field(arg0).finish(),
|
||||||
|
Self::ScratchInsufficient => f.write_str("ScratchInsufficient"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, STORAGE: Storage, STATE: State> Exchange<STORAGE, STATE> for Scratch<'a>
|
impl<STORAGE: Storage, STATE: State> Exchange<STORAGE, STATE> for Scratch
|
||||||
where
|
where
|
||||||
STORAGE::Error: Debug,
|
STORAGE::Error: Debug,
|
||||||
STATE::Error: Debug,
|
STATE::Error: Debug,
|
||||||
|
@ -40,6 +41,7 @@ where
|
||||||
|
|
||||||
fn exchange<const INTERNAL_PAGE_SIZE: usize>(
|
fn exchange<const INTERNAL_PAGE_SIZE: usize>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
config: &Config,
|
||||||
storage: &mut STORAGE,
|
storage: &mut STORAGE,
|
||||||
state: &mut STATE,
|
state: &mut STATE,
|
||||||
progress: ExchangeProgress,
|
progress: ExchangeProgress,
|
||||||
|
@ -56,6 +58,10 @@ where
|
||||||
assert_ne!(a.size, 0);
|
assert_ne!(a.size, 0);
|
||||||
assert_ne!(b.size, 0);
|
assert_ne!(b.size, 0);
|
||||||
|
|
||||||
|
if config.scratch_bank.size < INTERNAL_PAGE_SIZE as u32 {
|
||||||
|
return Err(ExchangeError::ScratchInsufficient);
|
||||||
|
}
|
||||||
|
|
||||||
let size = a.size; // Both are equal
|
let size = a.size; // Both are equal
|
||||||
|
|
||||||
let full_pages = size / INTERNAL_PAGE_SIZE as Address;
|
let full_pages = size / INTERNAL_PAGE_SIZE as Address;
|
||||||
|
@ -74,6 +80,8 @@ where
|
||||||
let a_location = a.location;
|
let a_location = a.location;
|
||||||
let b_location = b.location;
|
let b_location = b.location;
|
||||||
|
|
||||||
|
let scratch_bank_pages = config.scratch_bank.size / INTERNAL_PAGE_SIZE as u32;
|
||||||
|
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for page_index in page_index..full_pages {
|
for page_index in page_index..full_pages {
|
||||||
let offset = page_index * INTERNAL_PAGE_SIZE as u32;
|
let offset = page_index * INTERNAL_PAGE_SIZE as u32;
|
||||||
|
@ -81,8 +89,9 @@ where
|
||||||
let a_location = a_location + offset;
|
let a_location = a_location + offset;
|
||||||
let b_location = b_location + offset;
|
let b_location = b_location + offset;
|
||||||
|
|
||||||
let scratch_index = page_index as usize % self.pages.len();
|
let scratch_index = page_index % scratch_bank_pages;
|
||||||
let scratch_location = self.pages[scratch_index].start;
|
let scratch_offset = scratch_index * INTERNAL_PAGE_SIZE as u32;
|
||||||
|
let scratch_location = config.scratch_bank.location + scratch_offset;
|
||||||
|
|
||||||
log::trace!(
|
log::trace!(
|
||||||
"Exchange: Page {}, from a ({}) to b ({}) using scratch ({})",
|
"Exchange: Page {}, from a ({}) to b ({}) using scratch ({})",
|
||||||
|
|
|
@ -47,6 +47,8 @@ pub struct Config {
|
||||||
pub update_bank: Bank,
|
pub update_bank: Bank,
|
||||||
/// bank the bootloader is contained in, switching between banks
|
/// bank the bootloader is contained in, switching between banks
|
||||||
pub bootloader_bank: Bank,
|
pub bootloader_bank: Bank,
|
||||||
|
/// bank the pages are temporarily stored when using the `Scratch` exchange method
|
||||||
|
pub scratch_bank: Bank,
|
||||||
// Initial Image is stored to this bank after first update, restore on failure
|
// Initial Image is stored to this bank after first update, restore on failure
|
||||||
// pub golden_bank: Bank,
|
// pub golden_bank: Bank,
|
||||||
/// section of RAM of this device
|
/// section of RAM of this device
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub mod cortex_m {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(&mut self, config: &crate::hardware::Config) {
|
fn setup(&mut self, _config: &crate::hardware::Config) {
|
||||||
// Nothing to do!
|
// Nothing to do!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,13 @@ pub struct MoonbootManager<CONTEXT: Context, const INTERNAL_PAGE_SIZE: usize> {
|
||||||
processor: CONTEXT::Processor,
|
processor: CONTEXT::Processor,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "use-defmt", derive(Format))]
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct InitError;
|
pub struct InitError;
|
||||||
|
|
||||||
pub enum MarkError<E> {
|
#[cfg_attr(feature = "use-defmt", derive(Format))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum MarkError<E: core::fmt::Debug> {
|
||||||
UpdateQueuedButNotInstalled,
|
UpdateQueuedButNotInstalled,
|
||||||
State(E),
|
State(E),
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ pub struct MoonbootState {
|
||||||
/// RAM. As long as you don't want to perform update download, power cycle the device, and then
|
/// RAM. As long as you don't want to perform update download, power cycle the device, and then
|
||||||
/// apply the update, storing it in volatile memory is fine.
|
/// apply the update, storing it in volatile memory is fine.
|
||||||
pub trait State {
|
pub trait State {
|
||||||
type Error;
|
type Error: Debug;
|
||||||
|
|
||||||
/// Read the shared state
|
/// Read the shared state
|
||||||
fn read(&mut self) -> Result<MoonbootState, Self::Error>;
|
fn read(&mut self) -> Result<MoonbootState, Self::Error>;
|
||||||
|
|
Loading…
Reference in a new issue