I'm using the MKL17Z256VLH4 with interrupt-driven LPUART0. When transmitting more than one byte the following bytes are always zero, regardless of what is passed to the subsequent calls of LPUART_WriteByte(), which is in LPUART_TX_RX_IRQHandler().
Here is just the transmit portion of my ISR:
if(kLPUART_TxDataRegEmptyFlag & status && (((LPUART_Type*)UART_SEL[uart])->CTRL & LPUART_CTRL_TIE_MASK))
{
if(TxMsg[uart].pos < TxMsg[uart].length && SCI_PAR_NONE2 != TxMsg[uart].parity) {
LPUART_WriteByte(UART_SEL[uart], TxMsg[uart].data[TxMsg[uart].pos++]); // << breakpoint here
} else {
// Message is sent.
LPUART_DisableInterrupts(UART_SEL[uart], kLPUART_TxDataRegEmptyInterruptEnable);
LPUART_EnableInterrupts(UART_SEL[uart], kLPUART_TransmissionCompleteInterruptEnable);
}
}
I noticed that when I set a breakpoint on the call to LPUART_WriteByte() the data bytes started transmitted correctly (most of the time), so I added a software delay to see what would happen:
for (int i = 100000; i > 0; i--);
LPUART_WriteByte(UART_SEL[uart], TxMsg[uart].data[TxMsg[uart].pos++]);
The data started coming through (monitored with RealTerm), but it's inconsistent. Clearly there is something wrong here. I've stepped through and verified, using the expressions and memory view windows in KDS, that the data being sent to LPUART_WriteByte() is correct. I've also connected a logic analyzer to the LPUART0 transmit and receive lines and verified that the data coming out of the micro is not correct.
There's clearly something wrong with either the LPUART0 or my use of it. Any insight anyone can offer would be much appreciated.
Solved! Go to Solution.
Thanks, Mark, for the good suggestions. It turned out that a message buffer was being shared by both the transmit and receive sides of the application (inherited code from my predecessor), and they were stomping on each other. Modifying the code to use separate buffers for transmit and receive resolved the problem.
Jim
I don't see anything obvious - the following is the same LPUART interrupt handler in the uTasker project (used in many KL17/KL27 products and no problems experienced):
// Generic LPUART interrupt handler
//
static __interrupt void _LPUART_interrupt(KINETIS_LPUART_CONTROL *ptrLPUART, int LPUART_Reference) // generic LPUART interrupt handler
{
unsigned long ulState = ptrLPUART->LPUART_STAT; // status register on entry to the interrupt routine
..
if (((ulState & LPUART_STAT_TDRE) & ptrLPUART->LPUART_CTRL) != 0) { // if transmit buffer is empty and the transmit interrupt is enabled
fnSciTxByte((QUEUE_LIMIT)LPUART_Reference); // transmit data empty interrupt - write next byte, if waiting
}
..
}
fnSCITxByte() does the same as yours (feeds the next byte or disables further interrupts).
However, when I look again I would review carefully the brackets in
if(kLPUART_TxDataRegEmptyFlag & status && (((LPUART_Type*)UART_SEL[uart])->CTRL & LPUART_CTRL_TIE_MASK))
It sounds as though your interrupt may be reentering faster than you expect and thus cause you to overrun the output buffer if this were not right (check the interrupt with a port toggle at each occurrence and maybe you will have surprised - it should reenter only once per character (somewhere around the last data bit transmission).
Regards
Mark
uTasker developer and supporter (+5'000 hours experience on +60 Kinetis derivatives in +80 product developments)
Kinetis: http://www.utasker.com/kinetis.html
uTasker - for more performance and faster, cheaper product development
Thanks, Mark, for the good suggestions. It turned out that a message buffer was being shared by both the transmit and receive sides of the application (inherited code from my predecessor), and they were stomping on each other. Modifying the code to use separate buffers for transmit and receive resolved the problem.