embassy-rs/embassy · error
OTP not present
Error message
OTP not present
What it means
Generated into the flash driver: when no OTP region is present in the chip's memory map, `otp` compiles to `panic!("OTP not present")`. It fires at runtime when user code reads the OTP (one-time-programmable) flash area on a chip where embassy-stm32 has no OTP base address.
Solutions
- Gate OTP usage behind a chip check — only read OTP on parts known to expose it.
- Verify the target chip actually has an OTP region and that embassy-stm32's metadata includes it; update the chip data if it's missing.
- Replace OTP reads with another storage (e.g. a flash sector) on chips without OTP.
Example fix
// before
let mut otp = flash.in_otp().unwrap();
otp.read(0, &mut buf);
// after
#[cfg(feature = "chip-with-otp")]
{
let mut otp = flash.in_otp().unwrap();
otp.read(0, &mut buf);
} Defensive patterns
Strategy: validation
Validate before calling
// feature-gate OTP use
#[cfg(feature = "has-otp")]
fn read_otp(flash: &mut Flash) { let mut otp = flash.in_otp().unwrap(); otp.read(0, &mut buf); } Prevention
- Only call in_otp()/OTP reads on chips documented to have OTP.
- Verify OTP region presence in embassy-stm32 chip data when porting.
- Provide a fallback source (flash sector) for values usually read from OTP.
When it happens
Trigger: Calling `flash.in_otp()` / OTP region reads on a chip whose memory-map data has no region named "OTP", so `otp_base` stays None in build.rs.
Common situations: Porting code that reads factory OTP (e.g. MAC addresses) from one STM32 family to a chip that lacks a modeled OTP region; missing metadata for newly supported chips.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Bank 1 not present
- Bank 2 not present
- Both 'single-bank' and 'dual-bank' features enabled
- Chip supports single and dual bank configuration. No Cargo…
- attempted to use peripheral
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/5099d998b292cdd1.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-stm32/build.rs:547
let mut otp_base = None;
for region in flash_memory_regions.iter() {
if region.name == "BANK_1" || region.name == "BANK_1_REGION_1" {
bank_1_base = Some(region.address);
} else if region.name == "BANK_2" || region.name == "BANK_2_REGION_1" {
bank_2_base = Some(region.address);
} else if region.name == "OTP" {
otp_base = Some(region.address);
}
}
let bank_1 = bank_1_base
.map(|a| quote!(#a))
.unwrap_or_else(|| quote!(panic!("Bank 1 not present")));
let bank_2 = bank_2_base
.map(|a| quote!(#a))
.unwrap_or_else(|| quote!(panic!("Bank 2 not present")));
let otp = otp_base
.map(|a| quote!(#a))
.unwrap_or_else(|| quote!(panic!("OTP not present")));
let (swap_check, bank1, bank2) = if check_fb_mode {
(
quote! { let is_swapped = crate::pac::SYSCFG.memrmp().read().fb_mode(); },
quote! { if is_swapped { #bank_2 } else { #bank_1 } },
quote! { if is_swapped { #bank_1 } else { #bank_2 } },
)
} else {
(quote! {}, quote! { #bank_1 }, quote! { #bank_2 })
};
flash_regions.extend(quote! {
impl crate::flash::FlashBank {
/// Absolute base address.
pub fn base(&self) -> u32 {
#swap_check
match self {
crate::flash::FlashBank::Bank1 => #bank1,View on GitHub (pinned to 463a07b963)