STM32: Interrupt latency for serial protocol implementation
Note that the latency is 12 cycles only in ideal circumstances, when the interrupt vector table and handler code reside in 0 wait state memory. Internal flash can have 5 or 6 cycles latency, delaying the start even more, and causing substantial jitter depending on whether these areas are cached at the moment.

168 MHz / 614.4 kHz gives 273 cycles, which should be enough for one or two very short interrupt handlers, but it would seriously impact overall performance, as exiting an interrupt handler takes almost the same amount of cycles as entering.

Use DMA controlled by timers to read/write GPIO pins

The DMA2 controller in an STM32F1 or STM32F4 can copy values directly between GPIO registers and a buffer in main memory, triggered by a timer capture or compare event (among others). Should work on an F7 or H7 too.

Receiving:


Connect the incoming clock line to a channel of TIM1 or TIM8 (these two can trigger DMA2).
Set up the DMA channel associated with the timer channel to copy from GPIOx-&gt;IDR (where the incoming data is connected to) to the array in memory.
Set the timer channel to capture mode, generating a DMA request on the rising or falling edge on the clock line as required.
When enough bits are accumulated, extract the data from the input buffer.


Transmitting:


Connect the transmit clock line to a channel of TIM1 or TIM8.
Set up the DMA channel associated with the timer channel to copy from an array in memory to GPIOx-&gt;BSRR (where the outgoing data line is connected to).
Set the timer channel to generate a PWM signal, and a DMA request on the compare event.
To control the number of bits transmitted, either use the repetition counter RCR (has to be manually reloaded after 8 bytes), or another timer as both slave and master, using the other timer to count clock cycles (external clock slave), and gate the clock output as a master.