This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430FR6928: Question about the UCTXIFG signal in the UART

Part Number: MSP430FR6928

According to the manual:

The UCTXIFG interrupt flag is set by the transmitter to indicate that UCAxTXBUF is ready to accept another character. An interrupt request is generated if UCTXIE and GIE are also set. UCTXIFG is automatically reset if a character is written to UCAxTXBUF. UCTXIFG is set after a PUC or when UCSWRST = 1. UCTXIE is reset after a PUC or when UCSWRST = 1.

These are the questions:
If I am not using interrupts and  I monitor the UCTXIFG flag and I don't try to send another character and I just clear the UCTXIFG flag ... does UCTXIFG get set immediately after, because UCAxTXBUF is still empty? In this case, is it safe to say that UCTXIFG and "UCAxTXBUF empty" (assuming such a signal existed) are complementary?.

if I AM using interrupts and I am using UCAIV to monitor UCTXIFG (I have UCTXIE and GIE  set) ... When UCAxTXBUF is empty an interrupt will be generate.  I service the interrupt but I don't write anything in the Tx Register ... Can I expect  another Tx interrupt to happen as soon as I finish the interrupt routine and I go back to my main program?

  • I've always wished the User Guide(s) would be a little more explicit about this. Based on Observed Behavior: UCTXIFG indicates the Event wherein the TX buffer becomes empty.; it is not a status flag. This means:

    1) If you explicitly clear UCTXIFG, it will not come back on until another byte is put in TXBUF and passes through to the shift register.

    2) Reading UCAIV (and getting back the UCTXIFG indicator) clears UCTXIFG, so this is the same as (1) above.

    A corollary is that if you do (1) or (2), you need to keep track of the fact that the IFG was set (recently). I personally avoid doing these -- I either write to TXBUF or clear UCTXIE.

  • Serial transmit interrupts are always tricky and typically require a bit of trial and error to figure out. It has been a while but looking at my code (in assembly)...

    Reading UCAIV clears the interrupt source so there will not be an immediate interrupt if you just return. Or at least my code is written that way.

            .func txint
    txint:  pushm.w #3,r15          ; save registers used (r13-r15)
            mov     #txqueue,r15    ; get char from queue
            call    #dequeue
            tst     r15
            jn      txempty         ; queue empty?
            mov.b   r15,&UCA0TXBUF  ; no, transmit char
            jmp     txdone
    txempty:
    
    txdone: popm.w  #3,r15          ; restore registers
            reti
            .endfunc
      

    This complicates things when you have new data to send.

  • 2) Reading UCAIV (and getting back the UCTXIFG indicator) clears UCTXIFG, so this is the same as (1) above.

    I am not so sure about that. It has been a while since I did this but my code reads UCAIV. The code to send a character (or put into FIFO queue) checks TXIFG. That code works so it would seem that reading UCAIV clears the transmit interrupt but leaves TXIFG set.

  • Appreciate your fast response. I still believe that I don't have a deep understanding of the issue. But I am following this rule of thumbs: The IV vectors are there to deal with the IFG flags and provide the jump to the proper piece of code (I use the switch/case template recommended by TI using C language). I allow these provided hardware registers to handle all the flags. Every time I need to send a string of characters through the serial port, I prepare the array and number of characters to be sent and then I enable the UCTXIE. Interrupts take place and when I reach the last character to be sent, I disable UCTXiE and write the last character to the Tx Buffer within the interrupt routine. I leave UCTXIFG alone. When I need to send another string of characters, I repeat the previous process and I enable UCTXIFG.

    Regards 

  • Hi Carlos,

    I saw you submitted another question to our CSC Team, ill answer that first:

     I also tried to look for an example that uses UCAIV in the service routine and I found nothing clear. In the user manual, there is the Example 30-1 you can read
    
    switch(__even_in_range(UCA0IV,18))
    
     I don’t think the 18 is right. 0x08 is more like it (unless I’m wrong). There is no explanation for why this number is there, anyways.

    I agree with you here, that might be a typo or oversight in that particular example from the SDK. 

    switch(__even_in_range(UCA0IV,USCI_UART_UCTXCPTIFG)) is the typical use, with USCI_UART_UCTXCPTIFG being the highest value interrupt vector you should expect to see. 

    Both versions will work, using 0x08 is just allows the compiler to be a bit more efficient than if 18 is used (0x12). 

    For your original questions, ill answer those as directly as I can here in case anyone else needs this information as well. 


    These are the questions:
    If I am not using interrupts and  I monitor the UCTXIFG flag and I don't try to send another character and I just clear the UCTXIFG flag ... does UCTXIFG get set immediately after, because UCAxTXBUF is still empty? In this case, is it safe to say that UCTXIFG and "UCAxTXBUF empty" (assuming such a signal existed) are complementary?.

    No,  like Bruce said, the UCTXIFG should not be set again. Its set when the UCAxTXBUF is ready for another character. That occurs once, when the value is transferred to the transmit shift register. 

    I'm not sure why you would want to clear UCTXIFG if you weren't making use of interrupts though, you could just leave it alone and when you are ready to transmit you know the buffer was previously ready. 

    if I AM using interrupts and I am using UCAIV to monitor UCTXIFG (I have UCTXIE and GIE  set) ... When UCAxTXBUF is empty an interrupt will be generate.  I service the interrupt but I don't write anything in the Tx Register ... Can I expect  another Tx interrupt to happen as soon as I finish the interrupt routine and I go back to my main program?

    No, if you are switching on UCAxIV in your handler like in most of our examples, then you will clear the UCTXIFG that was triggered when the buffer cleared, so you will not get another.

    When you are ready to transmit again, you could write UCATXIFG to trigger another interrupt. You could also do something in your ISR like disable the transmit interrupt, set the UCTXIFG, and then re-enable it when you are ready to start servicing transmit interrupts again. If I understand your explanation in your second post this is basically what you are doing now. 

    Best Regards,
    Brandon Fisher

  • As I mentioned, what I am doing (I explained it in my follow-up) works. I just wanted to have a clear understanding of this module. I actually went through a similar problem when I was working with the TM320 family and the serial module. The bottom line, the EVENT sets the flag (in my mind ... an edge not a level sets the flag). I also understand your piece of code ... the .H file for the particular controller defines names for each of the cases rather than using case 2, case 4, etc. Names most of the time are more meaningful than numbers, specially when the code has to be reviewed month or years later.

    Regards

**Attention** This is a public forum