Interface for programming Option Bytes on stm32g family.

This should probably work for f family too. Untested.
This commit is contained in:
Tomasz bla Fortuna 2024-01-29 19:34:26 +01:00
parent 3cd0a54e0e
commit 4cd1c64117

View File

@ -30,6 +30,51 @@ pub(crate) unsafe fn unlock() {
} }
} }
/// This locks the option bytes, but doesn't "enable" or flash them.
pub(crate) unsafe fn opt_lock() {
pac::FLASH.cr().modify(|w| w.set_optlock(true));
}
/// Unlock option bytes registers according to RM0440 page 206.
/// Flash needs to be unlocked first to use this.
pub(crate) unsafe fn opt_unlock() {
// Unlock option bytes
if pac::FLASH.cr().read().optlock() {
pac::FLASH.optkeyr().write_value(0x0819_2A3B);
pac::FLASH.optkeyr().write_value(0x4C5D_6E7F);
}
}
/// This should flash the option bytes and restart the device.
/// If it returns - something went wrong (eg. option bytes are locked).
pub(crate) unsafe fn opt_reload() {
pac::FLASH.cr().modify(|w| w.set_optstrt(true));
while pac::FLASH.sr().read().bsy() {}
}
/// Program the option bytes according to procedure from RM0440. Pass a function
/// that changes required bits within the option bytes. On success, this
/// function doesn't return - it resets the device. Before calling it, check if
/// the option bytes were already programmed.
pub unsafe fn program_option_bytes(setter: impl FnOnce() -> ()) {
// Unlocking flash also waits for all flash operations to cease.
unlock();
opt_unlock();
assert_eq!(pac::FLASH.cr().read().optlock(), false);
// Call user setter and modify the bits.
setter();
// This should reset and configured the bits and not return.
opt_reload();
// But if we failed: cleanup.
pac::FLASH.cr().modify(|w| w.set_obl_launch(true));
opt_lock();
lock();
}
pub(crate) unsafe fn enable_blocking_write() { pub(crate) unsafe fn enable_blocking_write() {
assert_eq!(0, WRITE_SIZE % 4); assert_eq!(0, WRITE_SIZE % 4);
pac::FLASH.cr().write(|w| w.set_pg(true)); pac::FLASH.cr().write(|w| w.set_pg(true));