{"record":{"id":"7978c56adc7c9ecb","repo":"embassy-rs/embassy","slug":"sai-failed-to-enable-check-that-config-is-valid","errorCode":null,"errorMessage":"SAI failed to enable. Check that config is valid (frame length, slot count, etc)","messagePattern":"SAI failed to enable\\. Check that config is valid \\(frame length, slot count, etc\\)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-stm32/src/sai/mod.rs","lineNumber":702,"sourceCode":"                    w.set_syncout(syncout);\n                });\n            }\n        }\n\n        let tx_rx = if Self::is_transmitter(&ring_buffer) {\n            TxRx::Transmitter\n        } else {\n            TxRx::Receiver\n        };\n        regs::configure_cr1(ch, &config, tx_rx);\n        regs::configure_cr2(ch, &config);\n        regs::configure_frcr(ch, &config);\n        regs::configure_slotr(ch, &config);\n\n        ch.cr1().modify(|w| w.set_saien(true));\n\n        if !ch.cr1().read().saien() {\n            panic!(\"SAI failed to enable. Check that config is valid (frame length, slot count, etc)\");\n        }\n\n        Self {\n            sub_block,\n            _sck: sck,\n            _mclk: mclk,\n            _sd: sd,\n            _fs: fs,\n            ring_buffer,\n            info: T::info(),\n            state: T::state(),\n        }\n    }\n\n    /// Start the SAI driver.\n    ///\n    /// Only receivers can be started. Transmitters are started on the first writing operation.\n    pub fn start(&mut self) -> Result<(), Error> {","sourceCodeStart":684,"sourceCodeEnd":720,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-stm32/src/sai/mod.rs#L684-L720","documentation":"After setting SAIEN in CR1, the driver reads the bit back to confirm the peripheral actually enabled. Hardware refuses to enable when the SAI configuration is inconsistent (e.g. invalid frame length, slot count, or mode mismatch), so the driver panics instead of returning a silently dead peripheral.","triggerScenarios":"Creating a Sai new / sub-block with a SaiConfig whose frame length (FRCR), slot count (SLOTR), protocol, or synchronization settings are invalid for the selected mode, causing SAIEN to not stick.","commonSituations":"Frame length not matching the data/slot configuration; slot count of 0 or incompatible with frame sync; copying an I2S config that doesn't fit the chosen protocol; wrong master clock division.","solutions":["Validate frame length (FRCR) equals slot_count * slot_size (e.g. 8 slots x 16 bits = 128) and matches the mode.","Check slot count and slot enable mask in SLOTR are nonzero and consistent with the frame.","Verify CR1 settings: mode (master/slave), sync selection, and clock strobing are legal for your topology.","Cross-check the configuration against the reference manual's valid combinations for your SAI block."],"exampleFix":"// before\nframe_length: 0,\nslot_count: 0,\n// after\nframe_length: 128, // e.g. 8 slots * 16 bits\nslot_count: 8,","handlingStrategy":"validation","validationCode":"fn sai_config_is_consistent(cfg: &SaiConfig) -> bool {\n    cfg.frame_length > 0\n        && cfg.slot_count > 0\n        && cfg.frame_length == cfg.slot_count * cfg.slot_size\n        && cfg.slot_enable_mask != 0\n}","typeGuard":null,"tryCatchPattern":"// Panics cannot be caught in embedded; validate config before constructing:\nassert!(sai_config_is_consistent(&config), \"invalid SAI config\");\nlet sai = Sai::new(...);","preventionTips":["Ensure frame_length == slot_count * slot_size.","Set a nonzero slot enable mask in SLOTR.","Match master/slave, sync, and clock-strobe settings to your topology.","Copy configs from a working embassy-stm32 SAI example for your protocol (I2S/MSB/PCM)."],"tags":["sai","embedded","panic","audio","i2s"],"backgroundTag":"invalid-config-value","analyzedSha":"463a07b963419a1bfe61d5d597c44acb810afb8b","analyzedAt":"2026-09-10T13:38:26.660Z","contentChangedAt":"2026-09-10T13:38:26.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}