{"record":{"id":"9d7b7b076367bef0","repo":"embassy-rs/embassy","slug":"qspi-transfer-width-exceeds-configured-io-lanes","errorCode":null,"errorMessage":"QSPI transfer width exceeds configured IO lanes","messagePattern":"QSPI transfer width exceeds configured IO lanes","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-stm32/src/qspi/mod.rs","lineNumber":210,"sourceCode":"            self.bk1d0.as_ref(),\n            self.bk1d1.as_ref(),\n            self.bk1d2.as_ref(),\n            self.bk1d3.as_ref(),\n        );\n        let bk2 = bank_max(\n            self.bk2d0.as_ref(),\n            self.bk2d1.as_ref(),\n            self.bk2d2.as_ref(),\n            self.bk2d3.as_ref(),\n        );\n        bk1.max(bk2)\n    }\n\n    /// Panic if any width in `transaction` exceeds the wired-up IO lanes.\n    fn assert_transfer_widths(&self, transaction: &TransferConfig) {\n        let max = self.max_transfer_width();\n        if transaction.iwidth > max || transaction.awidth > max || transaction.dwidth > max {\n            panic!(\"QSPI transfer width exceeds configured IO lanes\");\n        }\n    }\n\n    /// Do a QSPI command.\n    pub fn blocking_command(&mut self, transaction: TransferConfig) {\n        self.setup_command(transaction);\n\n        while !T::REGS.sr().read().tcf() {}\n        T::REGS.fcr().modify(|v| v.set_ctcf(true));\n    }\n\n    /// Blocking read data.\n    pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) {\n        #[cfg(not(stm32h7))]\n        T::REGS.cr().modify(|v| v.set_dmaen(false));\n        self.setup_transaction(QspiMode::IndirectWrite, &transaction, Some(buf.len()));\n\n        let current_ar = T::REGS.ar().read().address();","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-stm32/src/qspi/mod.rs#L192-L228","documentation":"The QSPI controller only has as many IO lines wired up as configured (1, 2 or 4). assert_transfer_widths() checks the instruction, address, and data widths of every transaction against that maximum and panics if any of them requests more lanes than exist. This keeps bus configuration consistent with the hardware wiring.","triggerScenarios":"Submitting a TransferConfig with iwidth, awidth, or dwidth of FOURBITS (or any width above the configured max) to a Qspi set up for one- or two-line mode, via blocking_command/blocking_read/blocking_write, setup_auto_poll, or entering memory-mapped mode (enable_memory_map).","commonSituations":"Copy-pasting a quad-mode flash driver config onto a board wired for dual/single SPI; flash chip datasheet commands (e.g. quad fast read) used without the quad IO lanes being configured; enabling memory-mapped mode with a quad transaction on a dual-lane setup.","solutions":["Set transaction iwidth/awidth/dwidth to widths <= the configured max_transfer_width() (check your Qspi wiring/pins).","Reconfigure the Qspi instance with four IO pins if quad transfers are genuinely required.","For memory-mapped mode, ensure the memory configuration's widths match the wired lanes before calling enable_memory_map()."],"exampleFix":"// before (2-line QSPI)\nlet mut t = TransferConfig::new(cmd, QspiWidth::SING, None, QspiWidth::NONE, QspiWidth::FOUR);\nqspi.blocking_command(t);\n// after\nlet mut t = TransferConfig::new(cmd, QspiWidth::SING, None, QspiWidth::NONE, QspiWidth::DUAL);\nqspi.blocking_command(t);","handlingStrategy":"validation","validationCode":"fn widths_fit(transaction: &TransferConfig, max: QspiWidth) -> bool {\n    transaction.iwidth <= max && transaction.awidth <= max && transaction.dwidth <= max\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive allowed widths from your board's wired QSPI pins; document them next to the driver setup.","Never copy quad-mode transaction configs onto single/dual-wired boards.","Validate TransferConfigs in one helper before handing them to any QSPI call."],"tags":["rust","embedded","stm32","qspi","bus-width","validation"],"backgroundTag":"invalid-argument-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"}