const KEY1: u32 = 0x4567_0123;
const KEY2: u32 = 0xCDEF_89AB;
fn flash() -> ch32_metapac::flash::Flash {
ch32_metapac::FLASH
}
#[inline(always)]
fn wait_busy() {
while flash().statr().read().bsy() {}
}
pub fn unlock() {
flash().keyr().write(|w| w.set_keyr(KEY1));
flash().keyr().write(|w| w.set_keyr(KEY2));
flash().modekeyr().write(|w| w.set_modekeyr(KEY1));
flash().modekeyr().write(|w| w.set_modekeyr(KEY2));
flash().obkeyr().write(|w| w.set_optkey(KEY1));
flash().obkeyr().write(|w| w.set_optkey(KEY2));
}
pub fn lock() {
flash().ctlr().write(|w| {
w.set_lock(true);
w.set_flock(true);
});
}
pub struct FlashWriter {
erase_bit: u8,
write_bit: u8,
}
const PG: u8 = 0; const FTER: u8 = 17;
const OBPG: u8 = 4; const OBER: u8 = 5;
const OBWRE: u8 = 9; const STRT: u8 = 6;
impl FlashWriter {
pub const fn standard() -> Self {
Self {
erase_bit: FTER,
write_bit: PG,
}
}
pub const fn ob() -> Self {
Self {
erase_bit: OBER,
write_bit: OBPG,
}
}
pub fn check_wrprterr(&self) -> bool {
let statr = flash().statr().read();
if statr.wrprterr() {
flash().statr().write(|w| w.set_wrprterr(true));
return true;
}
if statr.eop() {
flash().statr().write(|w| w.set_eop(true));
}
false
}
#[inline(always)]
pub fn write_start(&self) {
let write_bit = self.write_bit as usize;
let ctlr_start = (1 << OBWRE) | (1 << write_bit);
flash().ctlr().write(|w| w.0 = ctlr_start);
}
#[inline(always)]
pub fn write(&self, addr: u32, value: u16) {
unsafe { core::ptr::write_volatile(addr as *mut u16, value) };
wait_busy();
}
#[inline(always)]
pub fn erase_start(&self) {
let erase_bit = self.erase_bit as usize;
let ctlr_start = (1 << OBWRE) | (1 << erase_bit);
flash().ctlr().write(|w| w.0 = ctlr_start);
}
pub fn erase(&self, addr: u32) {
let erase_bit = self.erase_bit as usize;
let ctlr = (1 << OBWRE) | (1 << erase_bit) | (1 << STRT);
flash().addr().write(|w| w.set_addr(addr));
flash().ctlr().write(|w| w.0 = ctlr);
wait_busy();
}
#[inline(always)]
pub fn operation_end(&self) {
let ctlr_end = 1 << OBWRE; flash().ctlr().write(|w| w.0 = ctlr_end);
}
}
pub fn is_boot_mode() -> bool {
flash().statr().read().boot_mode()
}
pub fn set_boot_mode(mode: bool) {
flash().boot_modekeyp().write(|w| w.set_modekeyr(KEY1));
flash().boot_modekeyp().write(|w| w.set_modekeyr(KEY2));
flash().statr().write(|w| w.set_boot_mode(mode));
}