#![no_std]
#![no_main]
use cortex_m_rt::entry;
use defmt_rtt as _;
use panic_halt as _;
use gd32e2_hal::fmc::{Error, Page};
use gd32e2_hal::pac;
use gd32e2_hal::prelude::*;
use gd32e2_hal::rcu::ClockConfig;
const PAGE: Page = Page::P63;
const MARKER: u32 = 0xDEAD_BEEF;
const ERASED: u32 = 0xFFFF_FFFF;
fn read_word(index: u8) -> u32 {
let addr = PAGE as u32 + index as u32 * 4;
unsafe { core::ptr::read_volatile(addr as *const u32) }
}
#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let mut fmc = dp.fmc.constrain();
let _rcu = dp.rcu.constrain().freeze(&mut fmc, ClockConfig::default());
defmt::info!(
"product id {:#010x}, prefetch {}",
fmc.product_id_code(),
fmc.is_prefetch_enabled()
);
defmt::info!(
"protection {}, option error {}, user {:#04x}, data {:#06x}",
fmc.protection_level(),
fmc.option_error(),
fmc.user_option(),
fmc.data_option()
);
defmt::info!(
"page at {:#010x}, protected {}, before: {:#010x}",
PAGE as u32,
fmc.is_protected(PAGE),
read_word(0)
);
let result = fmc.with_unlocked(|f| {
f.erase_page(PAGE)?;
defmt::info!("erased, word 0 = {:#010x}", read_word(0));
if read_word(0) != ERASED || read_word(255) != ERASED {
defmt::error!(
"erase left {:#010x} / {:#010x}",
read_word(0),
read_word(255)
);
}
f.program(PAGE, 0, MARKER)
});
match result {
Ok(()) => defmt::info!("programmed, word 0 = {:#010x}", read_word(0)),
Err(e) => defmt::error!("erase or program failed: {}", e),
}
if read_word(0) != MARKER {
defmt::error!("word 0 = {:#010x}, expected {:#010x}", read_word(0), MARKER);
}
match fmc.with_unlocked(|f| f.program(PAGE, 0, MARKER)) {
Err(Error::Program) => defmt::info!("second program rejected, as it should be"),
Err(e) => defmt::error!("second program failed with {}, expected Program", e),
Ok(()) => defmt::error!(
"second program was accepted, word 0 = {:#010x}",
read_word(0)
),
}
defmt::info!("done");
loop {
cortex_m::asm::wfi();
}
}