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.

UART interrupt disable

Other Parts Discussed in Thread: MSP430F1481

Hello,

 

we have a question concerning the USART interrupt handling using the MSP430F1481 device:

 

When the USART0 interrupt is triggered the recieved character should switch to the corresponding function handling the rest of the data transfer.

In order to not jump to the start of  the interrupt routine again when the next byte is recieved, the interrupt for RX is disabled in the Interrupt Enable Register (IE1) until the data transfer is completed.

But according to the family users guide disableing the URXIE0 also disables URXIFG0, which flags the incoming of a new, complete char.

 

Is this true, or is it still possible to poll the Interrupt Flag Register 1 for incoming bytes in U0RXBUF when the recieve interrupt has been disabled?

 

Kind regards,

Fabion et Fronk

 

  • Hmm, if you get a letter every day, would you stay day and night at the mailbox to avoid going out to it and back in once a day?

    That's what your description of what you do sounds like. Well, maybe you really have nothing to do in the meantime. But even if so, you can e.g. enter a low power mode until the ISR has received the last character, saving a LOT of power.

    For almost every 'normal' UART baudrate, you'll spend way more time waiting for the next byte than you can ever waste by entering and exiting the ISR for each byte. So if you insist on doing so, you don't need an ISR at all. Just do a busy-waiting in your main loop.

    But to answer your question:

    URXIFG0 is set each time a character is received and cleared when either URXBUF is read or an ISR is serviced. So clearing URXIE0 will not disable setting URXIFG0.
    On the contrary, when URXIE0 is set, URXIFG0 will be cleared as soon as the ISR is called, no matter whether URXBUF will ever be read.
    If you look at figure 13-11 (page 13-18 of slau049f.pdf), you'll see that URXIEx has no influence on URXIFGx.

  • Hello Jens-Michael,

     

    thank you for your help!

     

    Actually we won't wait all days and nights in front of the mail box. Instead we just go outside when something just arrived in the box and won't get in again until there's nothing in the pipe coming in the next few seconds.

     

    Means, when getting an RX Interrupt (possibly in low power mode) the interrupt routine is started and reads out the first byte from RXBUF. This byte serves as a command which switches to the corresponding routine handling the rest of the data transfer. The data transfer end is signaled by a CTS/RTS hardware handshake. So we're only polling the receive flag as long as theres something to receive. After everything was received we're enabling the interrupt and may go sleep or do something else.

    Hope it's clearer now. Thanks again for your advise.

     

    Fabion et Fronk

     

  • Fabion et Fronk said:
    thank you for your help


    You're welcome  :)

    Fabion et Fronk said:
    Instead we just go outside when something just arrived in the box and won't get in again until there's nothing in the pipe coming in the next few seconds.

    Considering that 'goiung out' takes 6 clock cycles, or, with 1MHz clock, 6 microseconds, you can easily calculate how long these few seconds are in comparison. Each second 'processor time' is like 166666 seconds real time (if 'going out' in realtime takes 6 seconds), which would be 46 hours. You see the relation? Actually 'all day' was even off by a factor of two :)
    Unless you're using a abudrate close to your CPU clock (which normally only happens with SPI transfers), you'll have plenty of processor cycles between two bytes.

    Even with 115kBaud, and only 1MHz MCLK, it is 87 clock cycles, or 8 times the amount it takes to exit and re-enter the ISR. Worst case.

    The better way to handle this is to 1) set a global variable to the number of expected bytes, go into LPM, let the processor wake up when a byte arrives, so the ISR can decrement the counter and store the received byte away, and when it was the last byte, exit LPM on ISR exit, else keep LPM by just exiting the ISR.

    Once the given number of bytes has arrived, the main code automagically continues.

    You can even split it into two parts: first, wait for 1 byte, then (in main) decide what to do and wait for the rest.

    Ypu can even use the ISR to just receive the command byte, thendisable the ISR and continue in main busy-waiting for the rest.

    If you do a busy-waiting in the ISR, the processor stays awake all the time inside the ISR. LPM or not wouldn't make the smallest difference to the power consumption. Everything is better than idling in an ISR.
    ISRs are meant to handle an event, as fast as possible, and not to contain your application code.

    But if you really want to continue this way (well, it WILL work, it's just not the 'smartest' way to do it), my other informations in my last post should be enough to solve the problem.

  • Hello Jens-Michael,

     

    Thank you very much again for taking the time.

    You are of course right, that using a polling mechanism is by far not as good as using an ISR. We just thought that it might be difficult to do such a process with different funtionality just within a single interrupt routine as the ISR is always executed at the address in the interrupt vector table.

    Simply setting up a global variable to solve this issue, didnt came to mind. So thanks a lot. We do now use two global variables to come around this issue. uart_CMD keeps the command during execution and is UART_IDLE (=0x00) else and a uint32_t variable called uart_SIZE read the size of the comming up data transfer the next four bytes (shifted and OR'ed) and serves as a counter as long as the transfer didnt reach the end. This also has the nice side-effect that we dont need to use the CTS/RTS handshake for signaling the end of a transmission.

    This had a huge impact on our code base as we can place the whole functionality in two ISRs (for RX and TX), put error handling somewhere else and still have lots of cpu time to run other functions and ISRs.

    As the MSP on our board mainly serves as an boot-configurator for a TMS320 DSP, there isnt that much to do, but it should still be able to handle controlling functions or otherwise go sleep while waiting for the next byte.

     

    So again, we like to thank you for making it clear (and insisting!) and coming up with this solution.

    Good luck to you by whatever you are doing!

     

    Regards,

    Fabion et Fronk

  • Fabion et Fronk said:
    Thank you very much again for taking the time.


    You're welcome. Actually, I'm learning myself while reading thorugh the forum and writing an explanation sometimes gives new impulses how to improve code I already wrote.

    To be true, this solution wasn't entirely mine. Someone else in a different thread here wrote his code this way. My own UART code is more generic, featuring a ringbuffer with timeout detection. It is more flexible for the variety of projects I'm working on. And better portable on high level for the three different MSPs and the AVR we're using.

    But I'm glad to have helped you. Extra processor time is a really useful thing for that additional functionality that's suddenly needed without prior notice :)

    Fabion et Fronk said:
    Good luck to you by whatever you are doing

    ´
    Thanks. Good luck to you too.

    p.s.: I'm developing (hardware and software) wireless sensors for industrial smart metering.

**Attention** This is a public forum