Skip to main content
Associate II
July 10, 2025
Question

Reducing interrupt latency on STM32U575

  • July 10, 2025
  • 4 replies
  • 676 views

I'm trying to implement a serial bit-stream input (PCM-style) on an STM32U575. I have set up an EXTI channel to capture the incoming clock signal and then I'm using the following code in the ISR to capture the data bits:

__attribute__ ((section(".RamFunc"))) void EXTI7_IRQHandler(void) {
	SPLITTER_CLK_OUT_GPIO_Port->ODR |= SPLITTER_CLK_OUT_Pin;

	if(haveFS == 0) {
		// CLK pulse whilst in idle state - is there a FS?
		if(PCM_FS_IN_GPIO_Port->IDR & PCM_FS_IN_Pin) {
			haveFS = 1;
			slotCount = 0;
			bitsCount = bits_per_slot;
			pDataSlot = pData;
		} else {
			return;
		}
	}

	// Read next data bit
	if(PCM_DATA_IN_GPIO_Port->IDR & PCM_DATA_IN_Pin) {
		*pDataSlot |= (1 << --bitsCount);	// Set bit
	} else {
		*pDataSlot &= ~(1 << --bitsCount);	// Clear bit
	}

	if(_internal.bitsCount == 0) {
		// Received one slot
		slotCount++;
		pDataSlot++;
		bitsCount = bits_per_slot;
	}

	// Have we received all slots?
	if(_internal.slotCount == _internal.total_slots) {
		// Signal done somehow?
		slotCount = 0;
		haveFS = 0;	// Now we need to expect another FS pulse...
	}

	__HAL_GPIO_EXTI_CLEAR_RISING_IT(PCM_CLK_IN_Pin);
	SPLITTER_CLK_OUT_GPIO_Port->ODR &= ~SPLITTER_CLK_OUT_Pin;
}

This works for incoming clock frequencies up to approx 2MHz, but I really need to be able to handle about 4MHz. I've got the main clock configured at 160MHz.

I think my immediate issue is the interrupt latency, using the pin toggles in the ISR I can measure ~250ns latency, even after attempting to run the ISR from RAM. I'm not overly familiar with the architecture of the M33 core etc. - hoping someone might be able to give me some suggestions on how to improve this further!

TIA

4 replies

MHoll.2
Senior III
July 10, 2025

Why not use the SAI interfaces? (reference manual rm0456 chapter 69)

Associate II
July 10, 2025

Unfortunately the PCM interface I'm using has 18 slots of 16bits, the SAI interfaces only seem to support up to 16 slots @ 16 bits.

waclawek.jan
Super User
July 10, 2025

And what about 9 slots of 32 bits?

JW

KnarfB
Super User
July 10, 2025

You may quench out a few cycles here and there, but such a high number of interrupts will, if feasible at all, use up the entire CPU. If so, why not simply using polling?

Alternatively, you may look into receiving with SPI with DMA triggered by the FS edge.

hth

KnarfB

Associate II
July 14, 2025

Hi @KnarfB - I've tried a simple example of using SPI with DMA to receive my bitstream, and it looks promising. How would I configure the DMA to be triggered by the FS edge? I've tried to set up my GPDMA channel with an EXTI trigger, but I still seem to have to call HAL_SPI_ReceiveDMA() before it will fire? Have I missed something?

KnarfB
Super User
July 15, 2025

Sorry, I don't have STM32U5 specific experience.

If calling HAL_SPI_ReceiveDMA is too slow, you may switch to register level or you may be able to trigger the DMA via a timer event triggered by a GPIO edge.

hth

KnarfB 

 

 

 

Tesla DeLorean
Guru
July 10, 2025

I'd use GPIO->BSRR write (singular) over GPIO->ODR RMW actions, those will be slow/constraining, as force stalling and bus transactions.

Now, for higher speed, I'd suggest looking at using DMA, triggered by a TIM->CHx, copying GPIO->IDR into a pattern buffer, that you can process at a more leisurely pace, and decimate interrupt loading.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Associate II
July 10, 2025

Thanks both - I'll try these and see how I get on

To follow on from your suggestion @Tesla DeLorean , I had been looking for a way to do this with TIM Input Capture, but I've not got anywhere with that