embassy-rs/embassy · error

QSPI data can't be sent with a data width of NONE

Error message

QSPI data can't be sent with a data width of NONE

What it means

A data phase was requested (data_len = Some(n>0)) but the data width is QspiWidth::NONE, so no lanes exist to move the data bytes. The library enforces that any data transfer uses an actual width and panics on the mismatch.

Solutions

  1. Set dwidth to SING, DUAL, or FOUR whenever data is transferred.
  2. If no data is involved, pass data_len = None together with dwidth = QspiWidth::NONE.

Example fix

// before
let t = TransferConfig::new(cmd, QspiWidth::SING, Some(addr), QspiWidth::SING, QspiWidth::NONE);
t.data_len = Some(4);
qspi.blocking_read(t);
// after
let t = TransferConfig::new(cmd, QspiWidth::SING, Some(addr), QspiWidth::SING, QspiWidth::SING);
qspi.blocking_read(t);
Defensive patterns

Strategy: validation

Validate before calling

fn data_width_ok(len: Option<usize>, w: QspiWidth) -> bool {
    !(len.is_some() && w == QspiWidth::NONE)
}

Prevention

When it happens

Trigger: Passing a TransferConfig with data_len = Some(len) and dwidth = QspiWidth::NONE into setup_transaction via blocking_read, blocking_write, setup_auto_poll, or setup_command.

Common situations: Setting only the data length in a config struct whose dwidth defaulted to NONE; command templates reused for data-bearing operations without updating dwidth.

Related errors


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/ffa07232249b35d0. Report an issue: GitHub.

Appendix: source

Thrown at embassy-stm32/src/qspi/mod.rs:384

    fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig, data_len: Option<usize>) {
        self.assert_transfer_widths(transaction);

        match (transaction.address, transaction.awidth) {
            (Some(_), QspiWidth::NONE) => panic!("QSPI address can't be sent with an address width of NONE"),
            (Some(address), _) => {
                // u32::bit_width was only stabilized in 1.97
                let address_bit_width = u32::BITS - address.leading_zeros();
                if address_bit_width > transaction.address_size.bit_width() as u32 {
                    panic!("QSPI address too large to be represented with the given address size");
                }
            }
            (None, QspiWidth::NONE) => {}
            (None, _) => panic!("QSPI address is not set, so the address width should be NONE"),
        }

        match (data_len, transaction.dwidth) {
            (Some(0), _) => panic!("QSPI data must be at least one byte"),
            (Some(_), QspiWidth::NONE) => panic!("QSPI data can't be sent with a data width of NONE"),
            (Some(_), _) => {}
            (None, QspiWidth::NONE) => {}
            (None, _) => panic!("QSPI data is empty, so the data width should be NONE"),
        }

        T::REGS.fcr().modify(|v| {
            v.set_csmf(true);
            v.set_ctcf(true);
            v.set_ctef(true);
            v.set_ctof(true);
        });

        while T::REGS.sr().read().busy() {}

        if let Some(len) = data_len {
            T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1));
        }

View on GitHub (pinned to 463a07b963)