STM32N6 SPI 吊挂
作者: jake-taf创建于 2026年3月5日更新于 2026年9月11日
blocking_read 执行的步骤
- 禁用 SPI (清除 CR1.SPE)。Embassy 文档中提到,这需要“避免过溢导致 SPI RX 状态机卡死…?”。
- 设置字节大小 (CFG1.DSIZE = 0x7 (8 位)),如果已经设置则跳过。
- 启用 SPI (设置 CR1.SPE)。
- 清空 RX FIFO (从 RX 数据寄存器中读取数据,直到 RXP 置位)。
- 等待 TX FIFO 中有空间 (SR.TXP 置位) (或 TI 帧格式错误,模式故障,CRC 错误,过溢)。
- 向 TX 数据寄存器写入零。
- 启动主机传输 (设置 CR1.CSTART)。
- 等待 RX FIFO 中有数据 (SR.RXP 置位) (或 TI 帧格式错误,模式故障,CRC 错误,过溢) [在此处陷入,因为 RXP 标志从未置位]
- 从 RX 数据寄存器读取数据。
测试代码
以下代码用于触发问题。实际上,它向 SPI 发送写入和读取请求。请注意,SPI 总是同时发送数据两个方向。写入实际上是(发送数据,丢弃接收数据),而读取是(发送零,接收数据)。 此代码写入两个随机选择的字节,然后读取数据。
let mut spi_config = spi::Config::default();
spi_config.frequency = Hertz(100_000);
let spi = spi::Spi::new_blocking(
p.SPI5, // SPI
p.PE15, // SCK
p.PG2, // MOSI
p.PH8, // MISO
spi_config,
);
let mut chip_select = Output::new(p.PA3, Level::High, Speed::VeryHigh);
loop {
let mut spi_buf = [33_u8; 1];
info!("SPI Buffer: {}", spi_buf);
chip_select.set_low();
spi.write(&[0x03_u8, 0x2c_u8]);
spi.read(&mut spi_buf);
chip_select.set_high();
info!("SPI Buffer: {}", spi_buf);
}RXP 标志(参考手册)
该标志由硬件改变。它监控当 SPI 启用时 RxFIFO 中当前可用的数据总数。RXP 值取决于 FIFO 阈值 (FTHLV[3:0])、数据帧大小 (SPI 模式下的 DSIZE[4:0] 和 I2S/PCM 模式下的 DATLEN[1:0]) 以及实际通信流。如果通过连续从 SPI_RXDR 中读取数据来读取数据包,则必须再次检查 RXP 标志,直到从 RxFIFO 中读取完整的数据包。
内容来源: embassy-rs/embassy