2025-10-01 10:54 PM
Hi,
I'm exploring using UART idle interrupt on RX to signal to my application that data has arrived.
I currently push data into a tx queue then start transmission. I rely on uart tx ISRs to check if there is any more data to send, then load up a DMA transfer.
UART TE is enabled once when the UART is enabled. I then rely on DMA to do everything. This currently works very well.
Can anyone suggest how I could squeeze and idle frame in? Ideally an idle frame will be inserted after each call to uart_dma_send, eg once per item in the transmit queue. My aim would be to keep my current transmit setup, where I can keep shoveling data into the transmit queue. Im using STM32F745. Probably I've missed something in the datasheet..
TX currently looks like:
void interface_uart_send_stuff(if_uart_t* p, uint8_t* stuff, uint16_t length) {
tx_q_push(p, length, stuff);
if (tx_state_is_busy()) {
// TX already happening, just queue up more to send
return;
}
// Start tx
tx_q_dta_t tx = tx_q_popI(&p->tx_q);
uart_dma_send(p->uart_dev, tx.n, tx.d);
}
// TX end of dma interrupt. Pack more data if needed
void interface_uart_tx_end_isr(if_uart_t* p) {
if (tx_q_sizeI(&p->tx_q) > 0) {
tx_q_dta_t tx = tx_q_popI(&p->tx_q);
// Send by DMA data d, length n
uart_dma_send(p->uart_dev, tx.n, tx.d);
} else {
// We enable the TC interrupt here so that is only called on the last DMA transfer
// from the transmit queue
p->uart_dev->uart->CR1 |= USART_CR1_TCIE;
}
}
// End of physical transmission interrupt
void interface_uart_tx_eot_isr(if_uart_t* p) {
if (tx_q_sizeI(&p->tx_q) > 0) {
tx_q_dta_t tx = tx_q_popI(&p->tx_q);
uart_dma_send(p->uart_dev, tx.n, tx.d);
} else {
tx_next_state(p, tx_ready_s);
}
}
2025-10-02 1:36 AM
@law__ wrote:I'm exploring using UART idle interrupt on RX to signal to my application that data has arrived.
How would idle help you detect that data has arrived ?
RXNE tells you when data has arrived.
And how does this relate to the rest of the question - which seems to be all about transmit ?
2025-10-02 3:18 AM
Hey,
> I'm exploring using UART idle interrupt on RX to signal to my application that data has arrived.
I'm just setting some context of what I'm doing. I have UART RX idle interrupt working well and it does what I want. The rest of my question is all about finding a pattern to insert an idle at the end of a TX by DMA. Ideally if there is data in the tx_q, I'd like to start it sending from within the interrupt. Otherwise I'll have to signal back to my application to start another UART transmit
Thanks
2025-10-02 4:32 AM
AFAIK there is no easy way to "inject" idle characters into the TX DMA flow. If you want to make pauses after each TX message, maybe start a timer at the TX DMA end event.
2025-10-02 4:35 AM
Wouldn't it be better to have a specific "end-of-message" marker?
2025-10-02 5:56 PM - edited 2025-10-02 5:57 PM
How would the end of message marker trigger an interrupt?
2025-10-02 6:06 PM - edited 2025-10-02 6:07 PM
I'd suppose that you'd create a TIM one-shot if you need fine timing, or flag something to handle in next SysTick interval. Or tag a CCRx point in the future for a fast maximal TIM to trigger on the time line.
Other might be able to send a slack or break character to the UART and catch a TC interrupt off that to light off next DMA TX operation.
2025-10-02 6:31 PM - edited 2025-10-02 6:32 PM
Thank you, sending a break character is an interesting idea. The receiver is not watching for break, so this could be ok. I'll check this out
I've also considered toggling TE in the TC interrupt to generate idle. I would have to poll on TEACK in the interrupt though.
2025-10-03 2:55 AM
Break can cause a frame error, the receiver should be ready to handle it.
2025-10-03 5:21 AM
It wouldn't as such.