Author Topic: UART TX Interrupt Flag raised by default? (MSP430)  (Read 3424 times)

0 Members and 1 Guest are viewing this topic.

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
UART TX Interrupt Flag raised by default? (MSP430)
« on: March 12, 2019, 02:33:44 pm »
This may have a completely obvious answer, so apologies if that's the case, but this has been giving me some real trouble.

I've been playing with some UART code on an MSP430 launchpad board, trying to move away from the arduino environment I'm so familiar with.
The code I wrote hasn't been doing what I wanted, so I've now narrowed it down to this.

Code: [Select]
#include "msp430g2553.h"
#include <stdio.h>

unsigned int InterruptFlags;

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD; // Stop the Watch dog

  //------------------- Configure the Clocks -------------------//

   DCOCTL  = 0;             // Select lowest DCOx and MODx settings
   BCSCTL1 = CALBC1_1MHZ;   // Set range
   DCOCTL  = CALDCO_1MHZ;   // Set DCO step + modulation

  //---------------- Configuring the LED's ----------------------//

   P1DIR  |=  BIT0 + BIT6;  // P1.0 and P1.6 output
   P1OUT  &= ~BIT0 + BIT6;  // P1.0 and P1.6 = 0

  //--------- Setting the UART function for P1.1 & P1.2 --------//

   P1SEL  |=  BIT1 + BIT2;  // P1.1 UCA0RXD input
   P1SEL2 |=  BIT1 + BIT2;  // P1.2 UCA0TXD output

  //------------ Configuring the UART(USCI_A0) ----------------//

   UCA0CTL1 |=  UCSSEL_2 + UCSWRST;  // USCI Clock = SMCLK,USCI_A0 disabled
   UCA0BR0   =  104;                 // 104 From datasheet table-
   UCA0BR1   =  0;                   // -selects baudrate =9600,clk = SMCLK
   UCA0MCTL  =  UCBRS_1;             // Modulation value = 1 from datasheet
   UCA0CTL1 &= ~UCSWRST;             // Clear UCSWRST to enable USCI_A0

   IE2 |= UCA0TXIE;
   IE2 |= UCA0RXIE;

   InterruptFlags = IFG2;

   _BIS_SR(LPM0_bits + GIE);         // Going to LPM0
}

  #pragma vector = USCIAB0TX_VECTOR
  __interrupt void TransmitInterrupt(void)
  {
    IFG2 &= ~UCA0TXIFG;
    InterruptFlags = IFG2;
  }

  #pragma vector = USCIAB0RX_VECTOR
  __interrupt void ReceiveInterrupt(void)
  {
    IFG2 &= ~UCA0RXIFG;
  }

And I've finally figured out by looking at the "InterruptFlag" variable in the debugger (CCS), that the transmit interrupt flag "UCA0TXIFG" appears to be raised when I enable the interrupts...

This means that as soon as my code runs, without any input, the TX interrupt is being called, which doesn't seem right.

Now I can just reset this bit straight after I enable the interrupt, but why does it give me the chance to do this first, instead of calling the interrupt straight away?

I'm sure I'm missing something obvious, but I think I need some help figuring it out.
Death, taxes and diode losses.
 

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
Re: UART TX Interrupt Flag raised by default? (MSP430)
« Reply #1 on: March 12, 2019, 02:52:53 pm »
Solved!

Apparently when USCI comes out of reset, the flag is set, so I should only set it when I've got data to send.
Death, taxes and diode losses.
 

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13748
  • Country: gb
    • Mike's Electric Stuff
Re: UART TX Interrupt Flag raised by default? (MSP430)
« Reply #2 on: March 12, 2019, 03:19:12 pm »
On most MCUs, by default TX int means "give me more data" ( in some cases this can be changed to assert at the end of transmission, for RS485 control) , so reasonable for it to be active as soon as enabled.
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
Re: UART TX Interrupt Flag raised by default? (MSP430)
« Reply #3 on: March 12, 2019, 04:23:59 pm »
That makes a lot of sense now, cheers Mike!
Death, taxes and diode losses.
 

Offline rhodges

  • Frequent Contributor
  • **
  • Posts: 306
  • Country: us
  • Available for embedded projects.
    • My public libraries, code samples, and projects for STM8.
Re: UART TX Interrupt Flag raised by default? (MSP430)
« Reply #4 on: March 12, 2019, 09:36:57 pm »
It is common for an interrupt service routine to check the TX interrupt ENABLE before looking at the TX buffer empty flag. The TX enable is only set when there is more data to send.
Currently developing STM8 and STM32. Past includes 6809, Z80, 8086, PIC, MIPS, PNX1302, and some 8748 and 6805. Check out my public code on github. https://github.com/unfrozen
 

Offline ebclr

  • Super Contributor
  • ***
  • Posts: 2328
  • Country: 00
Re: UART TX Interrupt Flag raised by default? (MSP430)
« Reply #5 on: March 13, 2019, 03:04:33 am »
This will help you void polishing bits, If you have installed ccs on driver C will work

http://localhost:55432/content/c:/ti/msp430ware_3_80_06_03/driverlib/doc/MSP430FR2xx_4xx/html/index.html#intro
 

Offline bson

  • Supporter
  • ****
  • Posts: 2270
  • Country: us
Re: UART TX Interrupt Flag raised by default? (MSP430)
« Reply #6 on: March 13, 2019, 10:37:00 pm »
You shouldn't clear TXIFG in the interrupt handler.  It's cleared automatically when you write to TXBUF.
The logic goes something like this:

B is a tx buffer (or ring, deque, etc)

send bytes in message M:
  check or busy wait for B to have enough space to hold M
  add M to B
  if TXIFG is set:
     TXBUF = next byte in B
   
tx interrupt handler:
  if B isn't empty:
     TXBUF = next byte in B

So while you get an interrupt initially when you enable interrupts (because TXBUF is empty), the interrupt handler shouldn't do anything since the buffer should have been initialized to empty.  Alternatively you can, if it bothers you, clear TXIFG in during initialization.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: UART TX Interrupt Flag raised by default? (MSP430)
« Reply #7 on: March 14, 2019, 01:41:51 am »
Quote
The TX enable is only set when there is more data to send.
Note that this implies that the TX ISR needs to disable the transmitter (or perhaps just the TX interrupt) when there isn't more data to send, which is substantially different from how you'd treat a UART in

And it means that the user-level code needs to handle re-enabling the transmitter or tx interrupt whenever it gets new data to send, and it's not already enabled.
There were UARTs that only interrupted on "tx regsiter BECAME available" (or perhaps it was just edge-triggered interrupt controllers?)  I don't think I've seen one in a long time.   In that case, you needed to make sure that the user-level code output the first character directly...
 

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13748
  • Country: gb
    • Mike's Electric Stuff
Re: UART TX Interrupt Flag raised by default? (MSP430)
« Reply #8 on: March 14, 2019, 09:35:15 am »
Quote
The TX enable is only set when there is more data to send.
Note that this implies that the TX ISR needs to disable the transmitter (or perhaps just the TX interrupt) when there isn't more data to send, which is substantially different from how you'd treat a UART in

And it means that the user-level code needs to handle re-enabling the transmitter or tx interrupt whenever it gets new data to send, and it's not already enabled.
There were UARTs that only interrupted on "tx regsiter BECAME available" (or perhaps it was just edge-triggered interrupt controllers?)  I don't think I've seen one in a long time.   In that case, you needed to make sure that the user-level code output the first character directly...
One way to  do this is to have only the interrupt code able initiate transmisison, and the user code force an interrupt when adding data to an empty tx buffer
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline bson

  • Supporter
  • ****
  • Posts: 2270
  • Country: us
Re: UART TX Interrupt Flag raised by default? (MSP430)
« Reply #9 on: March 15, 2019, 06:28:30 am »
One way to  do this is to have only the interrupt code able initiate transmisison, and the user code force an interrupt when adding data to an empty tx buffer
Hmmm... now we get into the annoying thing about the whole TI IFG business.

How do you determine if the TX register is empty?  The IFG is set!  So you want to interrupt... how?  Set the already set flag?
(It might be possible to clear it, and then either the UART sets it immediately again, or you get to manually set it.)

Either way, another very good habit is to make interrupt handlers ignore spurious interrupts by explicitly checking status bits and ignore the interrupt if nothing needs to be done.
« Last Edit: March 15, 2019, 06:35:48 am by bson »
 

Online mikerj

  • Super Contributor
  • ***
  • Posts: 3240
  • Country: gb
Re: UART TX Interrupt Flag raised by default? (MSP430)
« Reply #10 on: March 15, 2019, 01:02:23 pm »
It is common for an interrupt service routine to check the TX interrupt ENABLE before looking at the TX buffer empty flag. The TX enable is only set when there is more data to send.

This is required on micros like the PIC that have a common ISR for multiple peripherals, but not for 'normal' micros.  You you are executing in the interrupt handler then the interrupt enable flag must have been set to get you there.

Quote
The TX enable is only set when there is more data to send.
Note that this implies that the TX ISR needs to disable the transmitter (or perhaps just the TX interrupt) when there isn't more data to send, which is substantially different from how you'd treat a UART in

That's exactly how a typical interrupt driven UART would work, it's much the same as interrupt driven SPI.  To send data you add it to your FIFO buffer and enable the TX interrupt (if not already set).  In the TX interrupt handler you put the next byte of data into the UART TX buffer if it's available, otherwise you disable the TX interrupt.
 

Offline Rickta59

  • Newbie
  • Posts: 4
Re: UART TX Interrupt Flag raised by default? (MSP430)
« Reply #11 on: March 17, 2019, 05:01:30 pm »
It is common for an interrupt service routine to check the TX interrupt ENABLE before looking at the TX buffer empty flag. The TX enable is only set when there is more data to send.

This is required on micros like the PIC that have a common ISR for multiple peripherals, but not for 'normal' micros.  You you are executing in the interrupt handler then the interrupt enable flag must have been set to get you there.
I'm not sure if you are saying that the msp430g2553 is a 'normal'. I'm pretty sure the msp430g2553 USCI peripheral does use a single interrupt vector for the UART and I2C features (actually 2 vectors one for TX one for RX).  If you are using both I2C and UART you need to check which one is triggering. As far as the USCI peripheral and vectors used, it really depends on the actually msp430 part if it shares or doesn't share the interrupts.

To send data you add it to your FIFO buffer and enable the TX interrupt (if not already set).  In the TX interrupt handler you put the next byte of data into the UART TX buffer if it's available, otherwise you disable the TX interrupt.
Often with the msp430g2553 you are using the extremely limited memory for something else. It only has 512 bytes of ram. You need to share that with the stack and all other memory usage. I usually forego any output serial buffering and spinlock on write waiting for the peripheral TXBUF to be empty. I much prefer to use the msp430g2553's limited buffer memory for the receive queue where you can't control when you are going to receive data.

 

Offline ebclr

  • Super Contributor
  • ***
  • Posts: 2328
  • Country: 00
Re: UART TX Interrupt Flag raised by default? (MSP430)
« Reply #12 on: March 17, 2019, 06:53:52 pm »
// ISR
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(UCA0IV,USCI_UART_UCTXCPTIFG))
  {
    case USCI_NONE: break;
    case USCI_UART_UCRXIFG:
      P1OUT |= BIT0; // Switch on red LED when byte received; TX vector will switch it off, it should be a short flicker
      while(UCA0STATW&UCBUSY); // Busy-waits inside ISR is bad code, but this is a stupid simple example
      UCA0TXBUF = UCA0RXBUF+1;
      __no_operation();
      break;
    case USCI_UART_UCTXIFG:
      P1OUT &= ~BIT0;
      break;
    case USCI_UART_UCSTTIFG: break;
    case USCI_UART_UCTXCPTIFG: break;
    default: break;
  }
}
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf