2025-07-10 2:53 AM
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
2025-07-10 4:46 AM
Why not use the SAI interfaces? (reference manual rm0456 chapter 69)
2025-07-10 5:58 AM
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.
2025-07-10 10:53 AM - edited 2025-07-10 10:54 AM
And what about 9 slots of 32 bits?
JW
2025-07-10 11:10 AM
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
2025-07-10 1:50 PM
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.
2025-07-10 1:55 PM
Unfortunately I think the overarching limitation is a maximum total frame size of 256bits for the SAI peripherals, so I'd only be able to get 8 slots of 32bits
2025-07-10 2:02 PM
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