2026-02-18 12:40 AM
Hello,
I'm working on a project where, per SPI channel, I need to:
I need to handle 3 channels like one described, so the blocking method is not possible.
For now, I manage to achieve a 25 kHZ update loop of a single channel update working in a loop, where after triggering MAX5719, I immediately trigger conversion of AD4630 and another SPI transfers.
My setup consists of:
My loop is affected by the transfer speed of the SPI in the following way:
I had a look a MDMA peripheral for optimising the CS switching and transfer, but it does not have direct access to the SPI register for transferring the data. I don't see ways to provide me with big improvements with just writing to bsrr registers using MDMA.
I look for ideas on how to increase the number (the goal would be to achieve 50 kHz+ loop).
2026-02-18 1:19 AM
One way to tackle this would be to generate both SPI clock and the chipselects using a cascade of timers, use the SPI hardware at STM32 as slave, feeding the clock from the timer output to SPI_SCK externally (by connecting pins). Then handle the incoming/outgoing SPI data using DMA.
This can be pulled out probably at any STM32; not something you can click in CubeMX, though.
JW
2026-02-18 1:57 AM
Thanks for the idea @waclawek.jan. I think I understand the idea. I will leave it as a backup since it needs additional hardware to trigger the AD4630 measurements and start clocking it after the measurement is ready.
Thinking more about it, performing a single DMA read of 24 bytes, then 12 bytes transfer sounds like the fastest way to do it.
2026-02-18 10:35 AM
> 2x6 bytes read and 2x3 bytes read
So an 18 byte read? Or does CS need toggled between reads?
I don't think there's an easy solution for this, and there's definitely not an easy HAL solution.
I would use register access to do this. If you can't block, then interrupts/DMA can work but takes more coding time.
2026-02-23 2:08 AM - edited 2026-02-23 2:09 AM
I forgot to press send last week. Yes it needs to change cs every transmit.
I managed to figure it out, so these are the key points I use to make it fast (For now, I got to 86kHz, 4 receives 4 transmits per cycle ).
Regarding SPI transfer:
Regarding my firmware:
Regarding cs:
I have one more question about this, according to mcu documentation (https://www.st.com/resource/en/reference_manual/rm0399-stm32h745755-and-stm32h747757-advanced-armbased-32bit-mcus-stmicroelectronics.pdf), page 2329 Transaction handling says:
A few data frames can be passed at single transaction to complete a message. The user
can handle number of data within a message thanks to values stored into TSIZE and TSER
fields. In principle, the transaction of a message starts when the SPI is enabled by setting
CSTART bit and finishes when the total number of required data is transacted. The end of
transaction controls the CRC and the hardware SS management when applied. To restart
the internal state machine properly, SPI is strongly suggested to be disabled and re-enabled
before next transaction starts despite its setting is not changed. If TSIZE is kept at zero
while CSTART is set, an endless transaction is initialized (no control of transfer size is
applied). During an endless transaction, the number of transacted data aligned with FIFOs
threshold is supported exclusively. If the number of data (or its grouping into packets) is
unpredictable, the user must keep the FIFO threshold setting (packet size) at single data
(FTHLV=0) to assure that each data frame raises its own packet event to be serviced by the
application or DMA.
Is there anything that can happen if I enable the SPI for transmit and receive, and always provide it with data when I write to CSTART register?
I planned to enable transmit and receive spi and use it to perform all 8 transfers in a single cycle, then disable it and enable it again for the next cycle.