embassy-rs/embassy · error

invalid word size

Error message

invalid word size

What it means

In bDMA channel configuration, the NDTR (number of data to transfer) computation panics when either the memory or peripheral side uses WordSize::EightBytes, which this hardware path does not implement. The library throws it early in configure() rather than programming a wrong word-size field. It signals the requested transfer width is invalid for this DMA instance.

Solutions

  1. Reconfigure the transfer with OneByte, TwoBytes or FourBytes word sizes on both sides
  2. Convert the u64 buffer to a u32 (or smaller) buffer before the transfer
  3. Verify the mem_len alignment assertion matches the chosen word size (mem_len % word_bytes == 0)
  4. Update the driver's match arms if the target chip's bDMA actually supports 64-bit sizes

Example fix

// before
let wsize = WordSize::EightBytes;
ch.configure(None, peri_addr, &mem_buf, ..., wsize, ...);
// after
let wsize = WordSize::FourBytes;
ch.configure(None, peri_addr, &mem_buf32, ..., wsize, ...);
Defensive patterns

Strategy: validation

Validate before calling

fn check_transfer(mem: &[u32], peri_ws: WordSize) {
    assert!(!matches!(peri_ws, WordSize::EightBytes));
    assert!(mem.len() > 0 && mem.len() <= 0xFFFF);
}

Type guard

fn is_valid_word_size(ws: WordSize) -> bool {
    !matches!(ws, WordSize::EightBytes)
}

Try / catch

if !is_valid_word_size(ws) {
    return Err(Err::WordSizeUnsupported);
}
ch.configure(..., ws, ...);

Prevention

When it happens

Trigger: Calling channel.configure()/start with mem or peri word size of EightBytes (e.g. &[u64] buffer); the match arm (WordSize::EightBytes, _) | (_, WordSize::EightBytes) is hit.

Common situations: DMA-ing arrays of f64/u64 samples; generic driver code instantiated with a 64-bit word type; buffer alignment mistakes leading a caller to pick the largest word size.

Related errors


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

Appendix: source

Thrown at embassy-stm32/src/dma/dma_bdma.rs:559

                };

                // NDTR is the number of transfers in the *peripheral* word size.
                // ex: if mem_size=1, peri_size=4 and ndtr=3 it'll do 12 mem transfers, 3 peri transfers.
                let ndtr = match (mem_size, peri_size) {
                    (WordSize::FourBytes, WordSize::OneByte) => mem_len * 4,
                    (WordSize::FourBytes, WordSize::TwoBytes) | (WordSize::TwoBytes, WordSize::OneByte) => mem_len * 2,
                    (WordSize::FourBytes, WordSize::FourBytes)
                    | (WordSize::TwoBytes, WordSize::TwoBytes)
                    | (WordSize::OneByte, WordSize::OneByte) => mem_len,
                    (WordSize::TwoBytes, WordSize::FourBytes) | (WordSize::OneByte, WordSize::TwoBytes) => {
                        assert!(mem_len % 2 == 0);
                        mem_len / 2
                    }
                    (WordSize::OneByte, WordSize::FourBytes) => {
                        assert!(mem_len % 4 == 0);
                        mem_len / 4
                    }
                    (WordSize::EightBytes, _) | (_, WordSize::EightBytes) => unimplemented!("invalid word size"),
                };

                assert!(ndtr > 0 && ndtr <= 0xFFFF);

                ch.par().write_value(peri_addr as u32);
                ch.m0ar().write_value(mem_addr as u32);
                ch.ndtr().write_value(pac::dma::regs::Ndtr(ndtr as _));
                ch.fcr().write(|w| {
                    if let Some(fth) = options.fifo_threshold {
                        // FIFO mode
                        w.set_dmdis(pac::dma::vals::Dmdis::Disabled);
                        w.set_fth(fth.into());
                    } else if mem_size != peri_size {
                        // force FIFO mode if msize != psize
                        // packing/unpacking doesn't work in direct mode.
                        w.set_dmdis(pac::dma::vals::Dmdis::Disabled);
                        w.set_fth(FifoThreshold::Half.into());
                    } else {

View on GitHub (pinned to 463a07b963)