use core::cell::RefCell;
use embassy_boot::BlockingFirmwareState;
use embassy_embedded_hal::flash::partition::BlockingPartition;
use embassy_rp::Peri;
use embassy_rp::flash::{Blocking, Flash};
use embassy_rp::peripherals::FLASH;
use embassy_sync::blocking_mutex::Mutex;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::once_lock::OnceLock;
use static_cell::StaticCell;
use super::DfuFlashManager;
pub const FLASH_SIZE: usize = 16 * 1024 * 1024;
pub const DFU_WRITE_SIZE: usize = 1;
pub(super) type FlashType = Flash<'static, FLASH, Blocking, FLASH_SIZE>;
pub(super) type MutexType = Mutex<CriticalSectionRawMutex, RefCell<FlashType>>;
pub(super) type PartitionType = BlockingPartition<'static, CriticalSectionRawMutex, FlashType>;
static FLASH_CELL: StaticCell<MutexType> = StaticCell::new();
static MANAGER: OnceLock<DfuFlashManager> = OnceLock::new();
pub fn init_flash(
flash_peri: Peri<'static, FLASH>,
storage_offset: u32,
storage_size: u32,
state_offset: u32,
state_size: u32,
dfu_offset: u32,
dfu_size: u32,
) -> PartitionType {
let raw_flash = Flash::<_, Blocking, FLASH_SIZE>::new_blocking(flash_peri);
let flash_mutex: &'static MutexType = FLASH_CELL.init(Mutex::new(RefCell::new(raw_flash)));
let mgr = DfuFlashManager::new(
flash_mutex,
storage_offset,
storage_size,
state_offset,
state_size,
dfu_offset,
dfu_size,
);
let partition = mgr.storage_partition();
MANAGER.init(mgr).ok();
partition
}
pub fn mark_booted() {
if let Some(mgr) = get_manager() {
let state_part = mgr.state_partition();
static ALIGNED: StaticCell<[u8; DFU_WRITE_SIZE]> = StaticCell::new();
let aligned: &'static mut [u8] = ALIGNED.init([0; DFU_WRITE_SIZE]);
let mut state = BlockingFirmwareState::new(state_part, aligned);
state.mark_booted().ok();
}
}
pub fn get_manager() -> Option<&'static DfuFlashManager> {
MANAGER.try_get()
}
pub fn init_flash_from_linkerscript(flash_peri: Peri<'static, FLASH>) -> PartitionType {
unsafe extern "C" {
static __bootloader_state_start: u8;
static __bootloader_state_end: u8;
static __bootloader_dfu_start: u8;
static __bootloader_dfu_end: u8;
static __bootloader_storage_start: u8;
static __bootloader_storage_end: u8;
}
init_flash(
flash_peri,
core::ptr::addr_of!(__bootloader_storage_start) as usize as u32,
core::ptr::addr_of!(__bootloader_storage_end) as usize as u32
- core::ptr::addr_of!(__bootloader_storage_start) as usize as u32,
core::ptr::addr_of!(__bootloader_state_start) as usize as u32,
core::ptr::addr_of!(__bootloader_state_end) as usize as u32
- core::ptr::addr_of!(__bootloader_state_start) as usize as u32,
core::ptr::addr_of!(__bootloader_dfu_start) as usize as u32,
core::ptr::addr_of!(__bootloader_dfu_end) as usize as u32
- core::ptr::addr_of!(__bootloader_dfu_start) as usize as u32,
)
}