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.

Not able to write anything to UCA0TXBUF since UCTXIFG gets reset when UCTXIE is set

Other Parts Discussed in Thread: MSP430F5418, MSP430F5438, MSP430F5436, MSP430F5419A

Using MSP430F5418, I am trying to  program SST25VF020 external flash  via spi. Since I want to do interrupt driven programming, I have enabled  both transmit and receive interrupts.


    P3DIR |= BIT2;   /* P3.2 OUT PIN for chip enable - 37 */
    P3OUT &= BIT2;   /* Set to high in the beginning */
 
    P3SEL |= BIT0;   /* Serial Clock Out - 35 */
    P3SEL |= BIT5;   /* UCA0SOMI  (Data In) - 40 */
    P3SEL |= BIT4;   /* UCA0SIMO  (Data Out)  - 39 */

    UCA0CTL1 = UCSWRST;
    UCA0CTL0 = UCMST + UCSYNC + UCMSB + UCCKPH;  
    UCA0CTL1 = UCSSEL__SMCLK;  
    UCA0CTL1 &= ~UCSWRST;
    UCA0IE = UCTXIE | UCRXIE;

 

During the above initialization, I get an interrupt when UCTXIE/UCRXIE is set. This causes the UCTXIFG also to get reset. I am not able to write anything to UCA0TXBUF due to this. Why doesn't UCTXIFG get set?

Please advise.

 

Ammamon

  • What I've done to prevent getting an interrupt immediately after enabling interrupts is to clear out the interrupt flags just before enabling the interrupts.

        UCA0CTL1 &= ~UCSWRST;

        UCA0IFG = 0;

        UCA0IE = UCTXIE | UCRXIE;

    I don't know why the UCTXIFG flag would get reset unless you are resetting it in your ISR.

     

    Good luck...

  • The 'UCTXIFG' gets set when you reset the UART. If your ISR is preset to transmit data on TX buffer empty interrupt, then simply setting 'UCTXIE' will start the transmit and a write to UCA0TXBUF is not needed to start the process.

    As suggested by 'blb', before setting 'UCTXIE', but after clearing reset mode, clear 'UCTXIFG'. Then, you can write to 'UCA0TXBUF' to start the transmit.

    Wayne

  • Thank you Wayne and blb for your answers.

    My problem is not yet resolved. I don't have any issue with the interrupt occurring when I set UCTXIE.

    The problem is actually with the UCTXIFG  not getting set for me to write to UCA0TXBUF.

    I am getting a transmit interrupt when I write to UCA0TXBUF for the first time  after UCTXIFG check as shown below. But after the interrupt occurs,   UCTXIFG is never set for further UCA0TXBUF writes.  

    This is the first time I am trying to use MSP430F5418 transmit buffer interrupts. With  receive interrupts, (ie. with UXRXIE alone set) I don't face any problem with UCTXIFG setting.

    Is there anything further needed to be done with transmit interrupt handling. TI has not supplied any code for transmit interrupt handling. Can someone provide me a complete example?

        P3DIR |= BIT2;   /* P3.2 OUT PIN for chip enable - 37 */
        P3OUT &= BIT2;   /* Set to high in the beginning */
     
        P3SEL |= BIT0;   /* Serial Clock Out - 35 */
        P3SEL |= BIT5;   /* UCA0SOMI  (Data In) - 40 */
        P3SEL |= BIT4;   /* UCA0SIMO  (Data Out)  - 39 */

        UCA0CTL1 = UCSWRST;
        UCA0CTL0 = UCMST + UCSYNC + UCMSB + UCCKPH; 
        UCA0CTL1 = UCSSEL__SMCLK;
        UCA0CTL1 &= ~UCSWRST;
        UCA0IE = UCTXIE | UCRXIE;
        while (!(UCA0IFG&UCTXIFG));               // USCI_A0 TX buffer ready?
        UCA0TXBUF = 1U;  //first dummy write

  • What does your ISR routine look like. As soon as you execute:

        UCA0IE = UCTXIE | UCRXIE;

    the IFG flag is set and causes an interrupt, so the while statement fails because the interrupt clears the IFG, unless you write to the TX buffer in the ISR.

    You want to write it like this:

        UCA0CTL1 = UCSWRST;
        UCA0CTL0 = UCMST + UCSYNC + UCMSB + UCCKPH; 
        UCA0CTL1 = UCSSEL__SMCLK;
        UCA0CTL1 &= ~UCSWRST;
        UCA0IE = UCTXIE | UCRXIE;

    ...

    #pragma vector=USCI_A0_VECTOR
    __interrupt void USCI_A0_ISR(void)
    {
        uint8_t volatile status;
        //uint8_t status2;
        uint8_t data;

        switch(__even_in_range(UART_IV,4))
        {
        case 0:     // Vector 0 - no interrupt
            break;

        case 2:     // Vector 2 - RX data
            status = UART_STAT;
            data  = UART_RXBUF;  // Read the data

            ....    

        break;

        case 4:     // Vector 4 - TX buffer empty

            UCA0TXBUF = 1U;  //first dummy write

            break;

        default:
            break;
        }
    }

    OR you want to do it like this:

        UCA0CTL1 = UCSWRST;
        UCA0CTL0 = UCMST + UCSYNC + UCMSB + UCCKPH; 
        UCA0CTL1 = UCSSEL__SMCLK;
        UCA0CTL1 &= ~UCSWRST;
        UCA0CTL1 = UCSSEL__SMCLK;
        UCA0IFG &= ~UCTXIFG;        // Clear the flag to avoid generating an interrupt

        UCA0IE = UCTXIE | UCRXIE;  // enable interrupts after clearing flag
        UCA0TXBUF = 1U;  // first dummy write will now write.

     

  • That last example should be:

    OR you want to do it like this:

        UCA0CTL1 = UCSWRST;
        UCA0CTL0 = UCMST + UCSYNC + UCMSB + UCCKPH; 
        UCA0CTL1 = UCSSEL__SMCLK;
        UCA0CTL1 &= ~UCSWRST;
     
        UCA0IFG &= ~UCTXIFG;        // Clear the flag to avoid generating an interrupt

        UCA0IE = UCTXIE | UCRXIE;  // enable interrupts after clearing flag
        UCA0TXBUF = 1U;                // first dummy write will now write.

     

  • Thank you so much for the reply. I am not setting or resetting any registers. My spi interrupt routine is having only domain specific code other than reading UCA0RXBUF.

    I have now removed the UCTXIE and changed my code to work with receipt interrupt alone. My application is working okay now.

     

    Dinesh

  • Ammamon Mon said:
    I am getting a transmit interrupt when I write to UCA0TXBUF for the first time  after UCTXIFG check as shown below. But after the interrupt occurs,   UCTXIFG is never set for further UCA0TXBUF writes.

    Ammamon Mon said:
    UCA0CTL1 = UCSWRST;

    This implicitely sets UCTXIFG and clears UCRXIFG. So UCTXIFG is always set now, UCTXBUG is clear.
    Ammamon Mon said:
    UCA0IE = UCTXIE | UCRXIE;
    Here you enable the interrupt requests for RX and TX. Since UCTXIFG is always set at this point, your TX ISR is called immediately. If you don't have one, the system will simply jump into the void, finally causing a reset. If you have one, it will now stuff something to TXBUF. so in teh next line, where you check UXTCIFG, it shoud be clear.

    Hwoever, setting  abreakpoitn on the while loop will trigger the breakpoint before TXIE adn RXIE are actually set (it has to do with the pilelining inside the processor code), so you get  abreakpoint (and see UCTXIFG set) jsut the moment before TXIE is set and causes the ISR to be called.

    If you don't have ISRs forhandlign TX and RX, don't set UCTXIE and UCRXIE. The IFG bits are set independently of the IE configuration. IFG means 'an event has occurred' and IE means 'if an event has occurred, call the ISR immediately'.

  • The important thing to remember is the reset state is for UCTXIFG bit to bet set. Namely:

        UCA0CTL1 = UCSWRST;
        UCA0CTL1 &= ~UCSWRST;

    Will cause the UCTXIFG flag to get set. If the flag is set and UCTXIE is set, an interrupt will happen.

    Wayne

  • I had the same problem for over a week!

    The bad thing is that it can be a lot of things...So, keep watching the specific register of the I²C channel you're working with.

    In my case, what I did to solve that was : 

    1)Remove any I²C connections between the Slave Device and the MSP before clicking the "Download and Debug" button

    2) Click the "Download and Debug" button

    3) Before Clicking the "go" button reconnect both SDA and SCL wires.

    4) Now press the "go" button.

    It worked for me using these platforms I use to work : MSP430F5436, MSP430F5438 and MSP430F5419A(which I'm using right now)

    I hope this works for you, and if it doesn't...don't give it up. :D

    João Benevides

  • Joao Benevides said:
    I had the same problem for over a week! [...] So, keep watching the specific register of the I²C channel you're working with.

    I doubt you had the same problem, since this thread was about SPI and not I2C (even though not explicitely stated anywhere).

    On I2C, TXIFG gets only set after setting the UCTXSTT bit. After SWRST, it is clear in I2C mode.

**Attention** This is a public forum