• Join
  • Sign In with my.TI Login
Texas Instruments
  • Products
  • Applications
  • Tools & Software
  • Support & Community
  • Sample & Buy
  • About TI
Sample & Purchase Cart Sample & Purchase Cart
  • Search
  • Advanced
TI E2E™ Community
  • Support Forums
  • Blogs
  • Groups
  • Videos
  • 简体中文
  • More ...
TI Home » TI E2E Community » Support Forums » Microcontrollers » MSP430™ Microcontrollers » MSP430 Ultra-Low Power 16-bit Microcontroller Forum » UART Tx ISR Problem
Share
MSP430™ Microcontrollers
  • Forum
  • Announcements
  • E2E Wiki
Options
  • Subscribe via RSS
MSP430 Resources
  • MSP430 Product Folder
  • MSP-EXP430G2 - MSP430 LaunchPad Value Line Development kit
  • MSP430 Getting Started Guide
  • MSP430 Microcontroller Projects
  • More Resources >
  • Forums

    UART Tx ISR Problem

    This question is answered
    Kevin Alden
    Posted by Kevin Alden
    on Mar 22 2012 14:04 PM
    Intellectual615 points

    I am using an MSP430 (MSP430x5xx family) MCU.  The code base currently has incoming and outgoing message handling code using UART0.  This works most of the time, but I just noticed that occasionally comms appears to go down.  

    After debugging I found that we are able to receive data with no problem, but at some point the Tx ISR stops triggering so no data ever gets sent.  If I manually set the UCA0IFG Tx bit in the debugger, things will start to work again until the error condition pops up again.  When I am in the bad state, the Tx interrupt is enabled.

    Does anyone have any idea what would stop the Tx ISR from firing?  

    The following is my Tx ISR code:

     UCA0IE &= ~UCTXIE;					// Disable tx interrupt

    if(numBytesInTxQueue == 0)
    { // Clear interrupt if nothing left in queue
    UCA0IFG &= ~UCTXIFG;
    }
    else
    {
    UCA0TXBUF= txByteQueue[readIndex++]; // Add next byte in queue to buffer
    numBytesInTxQueue--;
    }

    UCA0IE |= UCTXIE;
    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    All Replies
    • blb
      Posted by blb
      on Mar 22 2012 14:26 PM
      Expert2370 points

      Hi,

      Any chance that the numBytesInTxQueue is rolling over to zero as you are adding bytes to the txByteQueue?

      Regards,

      Barry

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jeff Tenney
      Posted by Jeff Tenney
      on Mar 22 2012 14:30 PM
      Verified Answer
      Verified by Kevin Alden
      Guru11130 points

      Hi Kevin,

      It looks like you might be misusing the UCTXIFG.

      You shouldn't clear UCTXIFG manually if you have nothing left to transmit.  Instead, just mask the interrupt with the IE register.  That leaves the IFG bit set as it should be.

      Also note that in the 5xx family, if you read the Interrupt Vector (UCA0IV) register and it shows a TX interrupt, it also automatically clears TXIFG for you.  In that case, you need to manually set the flag back to 1 if you see you have nothing to transmit.  So in the case of nothing left to transmit, mask the interrupt *and* set TXIFG.

      Your existing masking and unmasking statements (at the beginning and end of the posted code) are unnecessary.

      Jeff

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Kevin Alden
      Posted by Kevin Alden
      on Mar 22 2012 14:31 PM
      Intellectual615 points

      I don't think so.  Even it that could happen, I would see numBytesInTxQueue == 0 and just clear the interrupt.  The interrupt should keep firing in that case also.

      Also, there is a snippet of code I didn't include that detects when the index hits the end of the buffer and wraps it back to the beginning

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Kevin Alden
      Posted by Kevin Alden
      on Mar 22 2012 14:35 PM
      Intellectual615 points

      Jeff Tenney

      Hi Kevin,

      It looks like you might be misusing the UCTXIFG.

      You shouldn't clear UCTXIFG manually if you have nothing left to transmit.  Instead, just mask the interrupt with the IE register.  That leaves the IFG bit set as it should be.

      Also note that in the 5xx family, if you read the Interrupt Vector (UCA0IV) register and it shows a TX interrupt, it also automatically clears TXIFG for you.  In that case, you need to manually set the flag back to 1 if you see you have nothing to transmit.  So in the case of nothing left to transmit, mask the interrupt *and* set TXIFG.

      Your existing masking and unmasking statements (at the beginning and end of the posted code) are unnecessary.

      Jeff

      Interesting.  So I am using this completely wrong by clearing TXIFG.  

      In addition to masking the interrupt when nothing is left to transmit, I also need to unmask the interrupt when something is ready to transmit, correct?

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jeff Tenney
      Posted by Jeff Tenney
      on Mar 22 2012 14:40 PM
      Guru11130 points

      Kevin Alden
      I also need to unmask the interrupt when something is ready to transmit, correct?

      Yep.  Preferably in the "right" order -- insert tx char into output queue, then enable interrupt.

      Jeff

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • blb
      Posted by blb
      on Mar 22 2012 15:39 PM
      Expert2370 points

      Hi,

      That is interesting way of handling a transmit buffer. I've always left the interrupt enabled, filled the transmit queue and then kick start the transmission by sending the first byte to the TXBUF.  I can see advantages to doing it your way. You just fill up the transmit queue , set the TXIFG flag, enable the interrupt and away it goes.

      I believe my point about numBytesInTxQueue rolling to zero is still valid.  If you add a byte to the TX Queue and numBytesInTxQueue rolls over to zero, then when you come into the ISR, the TX queue is full, but it appears to be empty, because numBytesInTxQueue is zero. The TXIFG flag is cleared and the ISR is exited with nothing be transmitted. The TXIFG gets set when the TX Buffer is ready for more data, if nothing has been transmitted, the flag will not get set again.  You stated that if you set TXIFG via the debugger that it would start working again.  Probably not very likely, especially if numBytesInTxQueue is a 16 bit value, but still a possibility.

      Regards,

      Barry

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Kevin Alden
      Posted by Kevin Alden
      on Mar 22 2012 15:49 PM
      Intellectual615 points

      blb

      Hi,

      That is interesting way of handling a transmit buffer. I've always left the interrupt enabled, filled the transmit queue and then kick start the transmission by sending the first byte to the TXBUF.  I can see advantages to doing it your way. You just fill up the transmit queue , set the TXIFG flag, enable the interrupt and away it goes.

      I believe my point about numBytesInTxQueue rolling to zero is still valid.  If you add a byte to the TX Queue and numBytesInTxQueue rolls over to zero, then when you come into the ISR, the TX queue is full, but it appears to be empty, because numBytesInTxQueue is zero. The TXIFG flag is cleared and the ISR is exited with nothing be transmitted. The TXIFG gets set when the TX Buffer is ready for more data, if nothing has been transmitted, the flag will not get set again.  You stated that if you set TXIFG via the debugger that it would start working again.  Probably not very likely, especially if numBytesInTxQueue is a 16 bit value, but still a possibility.

      Regards,

      Barry

      Actually this is how I am doing it now.  I currently leave the interrupt enabled and then kick start the process by putting a byte into TXBUF to start the transmission.  I can now see some issues with the way the code is written though, one of them being the wrapping issue.  I am going to do some more investigation tomorrow and see what I can find.  Thanks for the help so far.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jeff Tenney
      Posted by Jeff Tenney
      on Mar 22 2012 16:05 PM
      Guru11130 points

      Barry, Kevin,

      Using the "kick-start" approach to transmit handling, how do you know that it is safe for the non-ISR code to put the first char into TXBUF?  I can't immediately think of a safe way to do it, so I'm curious how you do it.  How do you know there's not something already in TXBUF?

      Jeff

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Kevin Alden
      Posted by Kevin Alden
      on Mar 22 2012 16:14 PM
      Intellectual615 points

      Currently, I queue bytes one at a time into my local buffer when I want to transmit data.  If the local buffer is empty at the time of queueing, the byte is immediately put into TXBUF and never queued and I set a flag indicating this.  From this point on, all data will be queued into the buffer until the ISR has emptied it and my flag is cleared.  Then the process repeats.

      As I was typing that, something feels wrong.  I can't quite see where the problem would be, but the whole process seems overly complicated.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jeff Tenney
      Posted by Jeff Tenney
      on Mar 22 2012 16:34 PM
      Guru11130 points

      I can see how adding the extra flag you mentioned would help to address the problem.  But I can also see danger in handling the flag as well as one nasty potential race condition that would be hard (impossible) to debug.  Sounds like you have a good sixth sense for these weaknesses.

      Jeff

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • blb
      Posted by blb
      on Mar 22 2012 16:53 PM
      Expert2370 points

      Kevin,

      In my implementations, it is a command / response scenario. So I know that the transmitter is not in use when I start to build a message to be transmitted. 

      I can see how your method of using the IE to start the transfer would be superior when there is a constant stream of data to be transmitted.  Thanks for sharing. :)

      Regards,

      Barry

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • blb
      Posted by blb
      on Mar 22 2012 16:57 PM
      Expert2370 points

      Whoops I meant Jeff.  Dang it.  Sorry...

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Kevin Alden
      Posted by Kevin Alden
      on Mar 23 2012 12:57 PM
      Intellectual615 points

      So I tried making the mods you recommended and it didnt seem to matter.  One thing I noticed is if I take out my code that reads from an ADC module over i2c, my problems go away.  Basically, every half a second a set a flag to read from the ADC in my main loop.  I just commented out the call to my adc read function.

      Is there any way UCB0 (the i2c port im using) could interfere with UCA0 operation?

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Kevin Alden
      Posted by Kevin Alden
      on Mar 23 2012 14:57 PM
      Intellectual615 points

      The i2c issue was a separate problem.  Fixing both that problem and moving to your suggested interrupt handling scheme seems to have resolved my problem.  Thanks!

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    TI E2E™ Community
    • Support Forums
    • Blogs
    • Videos
    • Groups
    • Site Support & Feedback
    • Settings
    TI E2E™ Community Groups
    • TI University Program
    • Make the Switch
    • Microcontroller Projects
    • Motor Drive & Control
    Other Communities
    • Deyisupport
    • Designsomething.org
    • beagleboard.org
    • TI on Element 14
    • TI on TechXchangeSM
    Other Technical & Support Resources
    • WEBENCH® Design Center
    • Product Information Centers
    • Technical Documents
    • TI Design Network
    • TI Technical Articles
    • TI Training

    All content and materials on this site are provided "as is". TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with regard to these materials, including but not limited to all implied warranties and conditions of merchantability, fitness for a particular purpose, title and non-infringement of any third party intellectual property right. TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with respect to these materials. No license, either express or implied, by estoppel or otherwise, is granted by TI. Use of the information on this site may require a license from a third party, or a license from TI.

    Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms of Use of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms of Use of this site. TI, its suppliers and providers of content reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.

    Follow Us Texas Instruments on Facebook Texas Instruments on Twitter Texas Instruments on LinkedIn Texas Instruments on Google+
    TI Worldwide | Contact Us | my.TI Login | Site Map | Corporate Citizenship | mobile m.ti.com (Mobile Version)

    TI is a global semiconductor design and manufacturing company. Innovate with 100,000+ analog ICs and
    embedded processors, along with software, tools and the industry’s largest sales/support staff.

    © Copyright 1995-2013 Texas Instruments Incorporated. All rights reserved.
    Trademarks | Privacy Policy | Terms of Use