Search code examples
cinterruptuartdspic

dsPIC33EP256MC506 Uart TRMT not empty on interrupt


So I'm using the dsPIC33EP256MC506 and one of its UART for communication (9600,8,N,2). I need to get an interrupt when the Tx shift register is empty (TRMT = 1). By setting the UTXSEL bits to:

USTAbits.UTXISEL0 = 1;
USTAbits.UTXISEL1 = 0;

According to the data sheet UxSTA bit 15,13 UTXISEL[1:0]: = 01

11 = Reserved; do not use
10 = Interrupt when a character is transferred to the Transmit Shift Register (TSR) and as a result,
     the transmit buffer becomes empty.  
01 = Interrupt when the last character is shifted out of the Transmit Shift Register; all transmit
     operations are completed.  
00 = Interrupt when a character is transferred to the Transmit Shift Register (this implies there
     is at least one character open in the transmit buffer).

I know it says "...when the last character is shifted out..." which implies that the shift register isn't empty. On the other hand it also says "...all transmit operations are completed." which implies that the shift register should be empty.

However when the interrupt trig, the FIFO is empty and the TRMT = 0. So there is still a shift operation in progress.

TRMT: Transmit Shift Register Empty bit (read-only)
1 = Transmit Shift Register is empty and transmit buffer is empty (the last transmission has completed)
0 = Transmit Shift Register is not empty, a transmission is in progress or queued

On my Oscilloscope it looks like the interrupt is triggered somewhere among the stop bits.

I fail to see a practical difference between mode 10 and 01, both gives interrupt when there is data in the shift register. Can some one explain/confirm if this is yet another Microchip bug or what the practical difference is between mode 10 and 01.

What I really need is to know when the last stop bit has left the shift register.

MYSTERY SOLVED
It is a silicon bug and it's mentioned in the errata.

When using UTXISEL<1:0> = 01 (interrupt when last character is shifted out of the Transmit Shift Register) and the final character is being shifted out through the Transmit Shift Register (TSR), the Transmit (TX) interrupt may occur before the final bit is shifted out.


Solution

  • I guess you can consider it as a two-byte buffer.

    The first byte is the "transmit buffer", which software can write directly to (when it is empty). The second byte is the shift register, which reads bytes from the "transmit buffer" and shifts them onto the wire.

    10 mode tells you the transmit buffer is now empty (and you can write something else into it) since a byte just got moved into the shift register.

    01 mode tells you when the shift register got emptied, i.e. the entire byte is now on the wire.

    You can get an interrupt while the stop bit is being driven on the wire, because the stop bit is not part of the data in the shift register. All the data has been shifted out. The stop bit is "meta-data" as far as the MCU is concerned.

    It feels like I just re-stated what you said in different words. But it makes sense to me, so not sure which part has confused you.