2025-11-03 2:13 PM
As the subject line says, I've written a USART driver for a STM32H755 project where I want to detect a special end-of-line character, for implementing a simple command-line interface.
Originally this used DMA with the USART FIFOs disabled, but I recently changed the driver to use the 16-deep FIFOs with FIFO-threshold interrupts, because I am bit short on DMA channels.
I couldn't figure out why the character-match interrupt wasn't firing, so I paused execution to look at the USART registers after sending a short (12 characters) command from my serial terminal. I then refreshed the register view while looking at USART->RDR and was able to see the characters stored in the FIFO come out one by one.
Finally after the 12 bytes my "match" character appeared in RDR and then the CMF bit was set in ISR. This was what I was afraid of. The RM alludes to the fact that the receive FIFO stores some flags along with each received character. Well, apparently one of those flags is CMF.
I think this falls into that category of "technically correct but renders the functionality useless." If I'm interpreting correctly, the character-match function doesn't do anything useful when the USART FIFO is active. You want an interrupt to tell you that your magic character has arrived, but you won't get it unless you are reading the bytes one by one, obviating the need for a FIFO in the first place.
I would argue that this should be a chip errata, except it appears to be by design.
I'm posting here both for posterity, but also in the slim hope that someone will challenge my interpretation and tell me why it's wrong (and how to fix it without using DMA or getting an interrupt on every character).
Thanks.
2025-11-03 2:40 PM
> I'm posting here both for posterity, but also in the slim hope that someone will challenge my interpretation and tell me why it's wrong (and how to fix it without using DMA or getting an interrupt on every character).
CMF could have either been implemented in two ways:
Both have benefits.
In the second implementation, you are guaranteed the character is within the receiving buffer. With the first implementation, if CMF was set, the character may still be in the FIFO and not even read out yet. That seems less useful. How would you process/interpret the data when the data hasn't yet made it to the buffer? If you try to get it by reading RXDR directly now you have a race condition.
2025-11-03 5:28 PM - edited 2025-11-03 5:33 PM
@TDK wrote:With the first implementation, if CMF was set, the character may still be in the FIFO and not even read out yet. That seems less useful. How would you process/interpret the data when the data hasn't yet made it to the buffer? If you try to get it by reading RXDR directly now you have a race condition.
Hmmm, you haven't convinced me, but maybe I'm not seeing your point? Isn't learning that the magic character is *somewhere* in the FIFO, but not read out yet, the whole point of CMF? If you were reading out characters one by one, you could do the comparison yourself---no need for hardware assistance. (DMA is an exception, of course, which is how I was using it before.)
The point of having a FIFO is to reduce the interrupt rate so you read out data in chunks instead of one byte at a time. The natural disadvantage of reading data in chunks is that if there is a defined ending character (let's say CR or LF), you now have no ability to tell when that character has arrived. You're likely to have a partial data chunk waiting in the FIFO with no more incoming data to trigger the threshold interrupt. This is precisely where you'd want the CMF functionality, so you can empty the FIFO early.
What use case benefits from your second scenario (the one ST seems to have chosen)? Maybe you were assuming the use of DMA? But it's not really necessary to use the FIFO with DMA, so if your goal was to stop the DMA once the magic character arrives, you could just not use the FIFO---no harm.