# STM32: Interrupt latency for serial protocol implementation

I am implementing a synchronous serial interface (SDLC) using an STM32.

My original implementation for the RX side is running on a ARM7 which uses the FIQ to set an interrupt on the clock line, in the interrupt handler the bit is sampled from the data line and a short processing is done. The TX side is using the SPI hardware with the FIFO.

My question is: can a STM32 (F4/F7/H7) running at 168Mhz or more handle the interrupts fast enough? I have read that the interrupt latency should be around 12 cycles[1]

The current clock for the protocol is 153.6kbps but I need it to run also at 614.4kbps (4 times faster)

• What interface would that be? Is the data stream continuous? Why can't it be received via SPI or USART in synchronous mode, why it must be received with a clock edge interrupt? It can't tolerate interrupts being disabled, or too long processing in other interrupts then. – Justme Sep 15 '19 at 13:29
• Surely you don't actually need to bit-bang this? It really does sound like a job for either SPI or a USART in synchronous mode. – brhans Sep 15 '19 at 14:10
• if you ask this question it is very likely that the idea is wrong. Use the hardware to do the hard work! – P__J__ Sep 15 '19 at 17:21
• The TX part is done with SPI. The RX is right now implemented with an interrupt, the protocol is SDLC which uses bit stuffing with NRZI which means that it needs to be handled at the bit level and not at the byte level. Also note that the RX and TX have different clocks. – Uriel Katz Sep 15 '19 at 20:30

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->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->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.
• Sounds like a great idea! Using a timer with compare means I can create a very accurate clock right? i.e. I am not limited by some multiple of 2 (2-256) like in the SPI prescaler – Uriel Katz Sep 19 '19 at 15:24