Skip to content

Conversation

@BenChung
Copy link
Contributor

Adds a driver for the SPI peripheral.
Doesn't presently work (needs metapac work, it looks like), not yet tested in hardware.
Changes are still tied up in the I2C implementation.

  • Update the metapac for the pin definitions needed.
  • Get it working on hardware.
  • Add examples.

@BenChung
Copy link
Contributor Author

BenChung commented Jan 3, 2026

@decaday I'm having some issues with this on hardware (I'm in a sort of weird configuration, gee whiz). When transmitting as a SPI slave with DMA it mangles the last three bytes of the communication in a nonsensical way, even in 16 bit mode. In this example I'm transmitting 0x0100, 0x0202, 0x0303, 0x0404, then 0x0101, 0x0202, 0x0303, 0x0404, but then am getting 0x0100, 0x0202, 0x0000, 0x0000, 0x0303, 0x0401, 0x0102, 0x0203 back on the wire. Do you know if there's any errata about DMA and SPI?

image image

@BenChung
Copy link
Contributor Author

BenChung commented Jan 4, 2026

Okay, after quite a bit of headache I've concluded that DMA to SPI is broken. There's something wrong where if the DMA ever fills the TXFIFO up and if the DMA stops then the DMA can't be restarted properly and you start to lose bytes.

@decaday
Copy link
Member

decaday commented Jan 5, 2026

@BenChung
I checked the Application Note, and regarding SPI, I only found the following similar notes (which might not be directly related to your specific issue):

When receiving a stream of data as an SPI Master, an extra byte is generated, so the software needs to discard the first byte.

When transmitting as an SPI Master, using hardware Chip Select (NSS) is not recommended; software NSS is preferred. If you must use hardware NSS, the SPI peripheral must be disabled to release the line.

When transmitting as an SPI Master, an extra 0x00 is sent before every byte. To avoid this, a forced type cast on the Data Register is required (e.g., *((__IO uint8_t *)&SPI1->DR) = byte).

When writing directly to the DR register as an SPI Master, four NOP() instructions must be added immediately after the write operation to ensure successful transmission.

It is generally recommended to use the official library functions for SPI operations.

When using SPI in DMA mode, the SPI peripheral must be enabled before enabling the DMA channel.

Most of PY32's IPs are third-party STM32 clones, but there are differences. These IPs often have stricter register configuration requirements, quirky behaviors, or simply more Undefined Behavior (UB).

However, since SPI Slave with DMA is such a fundamental feature, I suspect there might be a way to avoid this issue or a specific workaround.

Is the code currently in the PR sufficient to test and reproduce the issue you mentioned? I would like to run some tests to verify a few hypotheses I have.

@BenChung
Copy link
Contributor Author

BenChung commented Jan 5, 2026

@decaday
Thank you! I've pushed my latest version; I'm testing in slave txonly mode using write in async mode. I'll put together a MWE if that'll help, though it'll take me a day or two.

When using SPI in DMA mode, the SPI peripheral must be enabled before enabling the DMA channel.

Hmm, the stock code starts with SPE=false when it sets the DMA up; otherwise everything looks right...

The behavior I'm seeing is that when the DMA backpressure on the TXFIFO stops it starts acting oddly and missing bytes. If I run in circular mode, for example, it's fine, but in a oneshot 4-byte transaction only one byte and three bytes of 0s make it.

@decaday
Copy link
Member

decaday commented Jan 6, 2026

@BenChung
Yes, adding a MWE would be very helpful.

I tried writing a standard DMA slave example today, but I wasn't able to reproduce the issue you described:
https://github.com/decaday/py32-hal/blob/bc/spi/examples/py32f030/src/bin/spi.rs

@BenChung
Copy link
Contributor Author

BenChung commented Jan 6, 2026

Huh - maybe it's because I'm using it in txonly mode. I'll throw something together tonight.

@BenChung
Copy link
Contributor Author

BenChung commented Jan 7, 2026

And when I MWEify it everything works perfectly. This is bizarre, sorry for the issues...

@decaday
Copy link
Member

decaday commented Jan 7, 2026

No worries at all. It happens to the best of us. Just let me know if the issue comes back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants