Hi,
We have a UART driver on a Kinetis K10DX using DMA to TX and single character interrupt for the RX.
It all works just fine but occasionally, very occasionally (like 10 days), it appears the Transmit Complete interrupt fails to fire causing us some problems.
I've poured over the code and put debug code in to try to re-create the problem without success.
I could put in a work around to check the state of TCFIFO after a timeout but this sound like a bit of a hack.
I think the question are:
1) Has anyone else had issues with the Transmit Complete interrupt (UART_S1_TC)?
2) Does anyone have any suggestions for a fix or a robust work around?
Cheers,
Here are the relevant bits of the driver:
// ===================================================================
// UART TX send buffer
// ===================================================================
void Uart0_TxBuff(UCHAR* buffer, USHORT length)
{
DMA_TCD2_BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(length); // set beginning loop count
DMA_TCD2_CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(length); // set loop current count
DMA_TCD2_SADDR = (ULONG)buffer; // set source address
DMA_SERQ = UART0_CHANNEL; // set enable request
UART0_C2 |= UART_C2_TCIE_MASK; // enable TX complete interrupts
}
// ===================================================================
// UART TX/RX Interrupt
// ===================================================================
void UART0_RX_TX_IRQHandler()
{
UCHAR data;
UCHAR statReg1 = UART0_S1; // save status register
if (statReg1 & (UART_S1_OR_MASK // is any error flag set?
| UART_S1_NF_MASK
| UART_S1_FE_MASK
| UART_S1_PF_MASK))
{
data = UART0_D; // consume any data and ignore it
}
else if (statReg1 & UART_S1_RDRF_MASK) // is RX data available?
{
data = UART0_D; // get data
rxFunction(data); // send client the received character
}
if ((UART0_C2 & UART_C2_TCIE_MASK) && // is TX complete enabled and
(statReg1 & UART_S1_TC_MASK)) // is TX complete?
{
UART0_C2 &= ~UART_C2_TCIE_MASK; // disable TX complete interrupts
responseCompleteFunction(); // notify client transmission complete
}
}
Solved! Go to Solution.
Hello Julian,
Is it possible to confirm that the responseCompleteFunction is not being called? It could be achieved through some LEDs or some flags (i.e. setting it before to call this function and clearing it inside the function).
Honestly, starting from this information, this behavior is very odd. I don't think this is happening but supposing that the interrupt handler is being executed, then it would mean that the TX flag is being cleared outside this function. Please double check that there is not another instruction in the code that is doing this.
At this moment, the only workaround that comes to mi mind is to do the same as the responseCompleteFunction does in the IRQ before to clear the TX interrupts.
Best regards,
Earl.
Hello Julian,
Your configurations seems to be ok, however, it is very difficult to find a solution without recreate the problem.
My advice is to wait for the MCU to fails, and once it fails attach the debugger to the running MCU. This will let you debug your system and look for the problem once the problem has been generated.
Attaching to a Running Target with Segger J-Link, GDB and Eclipse | MCU on Eclipse
Please let me know if this solution is helpful for you.
Best regards,
Earl.
Hi Earl,
I managed to capture some register details after the event.
It appears that there is no DMA error, no UART error, DMA has completed and the FIFO is empty. The TC complete flag is set and TCIE is reset suggesting that the interrupt had occurred but the responseCompleteFunction had not been called??
Here are the contents of the registers I managed to log:
C1 0x00
:C2 0xAC TIE,RIE,TE,RE (TCIE disabled)
:C3 0x0F errors enabled
:C4 0x03 BRFA
C5 0x80 TDMAS
:C6 0x00
BDL 0x41 19.2k,20MHz
:BDH 0x00 RXEDGIE disabled
S1 0xD0 TDRE,TC,IDLE
:S2 0x40 RXEDGIF (not enabled)
SFIFO 0xC0 TXEMPT,RXEMPT
:CFIFO 0x00
:PFIFO 0xAA fifo's enabled
RCFIFO 0x00 RX fifo empty
:RWFIFO 0x01 wmark = 1
:TCFIFO 0x00 TX fifo empty
:TWFIFO 0x01 wmark = 1
TCD2_SADDR 0x1FFFE738
CITER_ELINKNO 0x0019 TX length
:BITER_ELINKNO 0x0019 TX length
TCD2_CSR 0x0088 DONE,DREQ
:DMA_ERR 0x0000
DMA_ES 0x0000
DMA_CR 0x0084 EMLM(???),ERCA
NBYTES_MLOFFYES 0x80000401 SMLOE,MLOFF=1,NBYTES=1
We need to fix this urgently as it is becoming an serious issue for our customers.
In desperation I am thinking of trying the following:
a) Turning off the RX/TX FIFO's
b) Using DMA complete interrupt instead of UART TC interrupt
c) Not using DMA at all and ship the data out one character at a time!!
Can you see anything that may be causing the problem or think of anything else?
Cheers, Julian
Hello Julian,
Is it possible to confirm that the responseCompleteFunction is not being called? It could be achieved through some LEDs or some flags (i.e. setting it before to call this function and clearing it inside the function).
Honestly, starting from this information, this behavior is very odd. I don't think this is happening but supposing that the interrupt handler is being executed, then it would mean that the TX flag is being cleared outside this function. Please double check that there is not another instruction in the code that is doing this.
At this moment, the only workaround that comes to mi mind is to do the same as the responseCompleteFunction does in the IRQ before to clear the TX interrupts.
Best regards,
Earl.
Hi Earl,
I believe I have found the problem. After putting counters in the entry and exit of the ISR and callback I see that that the callback is being called!! I believe I have an issue with the state machine being pre-empted by the ISR which I can fix. I shall mark your last response as Correct Answer.
Thanks you so much for your assistance and patience :-)
Cheers, Julian
Thanks Earl,
Its good to know that at least there is nothing fundamentally wrong with the code.
It's going to be tricky getting access to the debug port as the modules are embedded in our system.
However, lets see what this shows up.
Cheers, Julian