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.

MSP430F2274: f2274

Part Number: MSP430F2274

Hi,

I am using "Linux debian 3.16.0-4-amd64 #1 SMP Debian 3.16.39-1+deb8u2 (2017-03-07) x86_64 GNU/Linux" , I have set up the msp430-gcc toolchain and able to run the blinky program on my msp430f2274. Now, I am moving to application development and before doing so, I'd like to setup the UART for debugging purpose. However, for some reason, I am unable to get the byte on the terminal. I have cross checked through my code and did not find any loopholes that may be causing this issue. Please find my source codes below,

1. gpio.c

/* Include's */
#include <msp430f2274.h>

/* Definitions */
#define MAX_PIN_NO_INVALID  255

/****************************************************************
 * Function Name :	gpio_configure
 * Description	 :	Configures GPIO as I/O
 * Returns	 :	0 = Success
                 	-1 = Fail
 * Params	 : 	@port_no = Port No.
                   	@pins_no = Pins in the port to configure
 ****************************************************************/
signed char
gpio_configure (unsigned char port_no, unsigned char pins_no)
{
  signed char ret = 0;
  if (pins_no > MAX_PIN_NO_INVALID)
    port_no = 0;
  switch (port_no)
    {
    case 1:
      P1DIR = pins_no;
      break;
    case 2:
      P2DIR = pins_no;
      break;
    case 3:
      P3DIR = pins_no;
      break;
    case 4:
      P4DIR = pins_no;
      break;
    default:
      ret = -1;
    }
  return (ret);
}

/****************************************************************
 * Function Name :	gpio_write
 * Description	 :	Sets gpio HIGH or LOW
 * Returns	 :	0 = Success
                       -1 = Fail
 * Params	 :	@port_no = Port No.
                        @pins_no = Pins to set HIGH or LOW
 ****************************************************************/
signed char
gpio_write (unsigned char port_no, unsigned char pin_no_val)
{
  signed char ret = 0;
  if (pin_no_val > MAX_PIN_NO_INVALID)
    port_no = 0;
  switch (port_no)
    {
    case 1:
      P1OUT = pin_no_val;
      break;
    case 2:
      P1OUT = pin_no_val;
      break;
    case 3:
      P1OUT = pin_no_val;
      break;
    case 4:
      P1OUT = pin_no_val;
      break;
    default:
      ret = -1;
    }
  return (ret);
}

/****************************************************************
 * Function Name :	gpio_read
 * Description	 :	Reads the status of the gpio
 * Returns	 :	0 or 1 = Success
                       -1 = Fail
 * Params	 :	@port_no = Port No.
                        @pins_no = Pin to be read
 ****************************************************************/
signed char
gpio_read (unsigned char port_no, unsigned char pin_no)
{
  signed char ret = 0;
  if ((pin_no == BIT0) || (pin_no == BIT1) || (pin_no == BIT2)
      || (pin_no == BIT3) || (pin_no == BIT4) || (pin_no == BIT5)
      || (pin_no == BIT6) || (pin_no == BIT7))
    {
      /* Do Nothing */
    }
  else
    {
      port_no = 0;
    }
  switch (port_no)
    {
    case 1:
      ret = P1IN & pin_no;
      break;
    case 2:
      ret = P2IN & pin_no;
      break;
    case 3:
      ret = P3IN & pin_no;
      break;
    case 4:
      ret = P4IN & pin_no;
      break;
    default:
      ret = -1;
    }
  return (ret);
}

/****************************************************************
 * Function Name :	gpio_mux
 * Description   :	Select GPIO alternate function
 * Returns       :	0 = Success
                       -1 = Fail
 * Params        :      @port_no = Port No.
                        @pins_no = Pins to mux
 ****************************************************************/
signed char
gpio_mux (unsigned char port_no, unsigned char pins_no)
{
  signed char ret = 0;
  if (pins_no > MAX_PIN_NO_INVALID)
    port_no = 0;
  switch (port_no)
    {
    case 1:
      P1SEL|= pins_no;
      break;
    case 2:
      P2SEL|= pins_no;
      break;
    case 3:
      P3SEL|= pins_no;
      break;
    case 4:
      P4SEL|= pins_no;
      break;
    default:
      ret = -1;
    }
  return (ret);
}

2. uart.c

/* Lib Includes */
#include <msp430f2274.h>
#include "gpio_driver.h"

/* Definitions */
#define UARTA0_PORT_NO		0x03	/* P3 */
#define UARTA0_PINS_MUX_VAL	0x30	/* P3.4(TXD) & P3.5(RXD) */

/* Local Function  Declarations */
static void uart_mux_pins ();
static void uart_configure ();

/*----------------Function Definitions-----------------*/
static void
uart_mux_pins ()
{
  signed char ret;
  if (ret = gpio_mux(UARTA0_PORT_NO, UARTA0_PINS_MUX_VAL) == -1)
    {
      /* Debug Code - LED blinks 5 times indicating a fault */
    }
  else
    {
      /* Debug Code - LED blinks 2 times indicating all good */
    }
}

static void
uart_configure ()
{
  /* Register Settings */
  UCA0CTL0 = 0x00;
  UCA0CTL1 |= UCSWRST + UCSSEL_2; 
  UCA0BR0 = 0x65;
  UCA0BR1 = 0x03;
  UCA0MCTL = UCBRS_1;
//  UCA0STAT |=  UCLISTEN;
  UCA0CTL1 &= ~UCSWRST;

  /* Enable TXD and RXD Interrupts */
  IE2 |= UCA0TXIE;
  IE2 |= UCA0RXIE;

  /* Enable Global/Maskable Interrupts */
  _BIS_SR (GIE);
}

void
uart_init ()
{
  uart_mux_pins ();
  uart_configure ();
}

//-----------------------------------------------------------------------//
//                Transmit and Receive interrupts                        //
//-----------------------------------------------------------------------//

#pragma vector  = USCIAB0TX_VECTOR
__interrupt void
TransmitInterrupt (void)
{
 gpio_write (0x01,0x01);
}

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

3. main.c

/* Lib Includes */
#include <msp430f2274.h>
#include "gpio_driver.h"
#include "uart_driver.h"

int
main ()
{
  signed char ret = 0;
  WDTCTL = WDTPW + WDTHOLD;	// Stop the Watch dog

  if (CALBC1_1MHZ == 0xFF)	// If calibration constant erased
    {
      while (1);		// do not load, trap CPU!!
    }

  DCOCTL = 0;			// Select lowest DCOx and MODx settings
  BCSCTL1 = CALBC1_8MHZ;	// Set range
  DCOCTL = CALDCO_8MHZ;		// Set DCO step + modulation 
  if (ret = gpio_configure (1, 0x01) == -1)
    {
      /* Debug Code - LED blinks 5 times indicating a fault */
    }
  uart_init ();
  UCA0TXBUF = 'A';
}

Currently, I am just looking to send a byte from the msp to the terminal (/dev/ttyAMC0). I am using the MSP430 Ez430-RF2500 Development Tool. I tried the loopback test as well, did not work. Any support to getting this to work would be helpful.Thanks.

-Vinay Divakar

  • What do you have connected to P3.4 and P3.5?
  • >TransmitInterrupt (void)
    >{
    gpio_write (0x01,0x01);
    >}

    This ISR doesn't do anything to clear the Tx interrupt. As soon as you set GIE, this interrupt will trigger continuously, and you'll never get to the point of writing to TXBUF.

    One simple fix is to move the UCA0TXBUF='A' into TransmitInterrupt. This will give you a stream of 'A' characters rather than a single one, but you may find that easier to debug. Longer term, you'll presumably be setting UCA0TXBUF in the ISR routinely.

    Unsolicited: My calculator says that 1MHz/0x365 is off by >4% from 1200bps. Only you know what you want to do here, but a divisor of 833=0x341 should get you 1200bps pretty much exactly.

  • , I haven't connected anything to P3.4 and P3.5. I presume they are already connected to a UART to USB converter onboard through which the bytes can be sent to and received from the serial terminal.

  • , I made the change you suggested and now I am getting a stream of 'A' characters on the serial terminal. However, I have some clarifications, just to make sure that my understanding is right and we are on the same page here.

    1. Regarding clearing the Tx interrupt, do you mean to say clearing the UCA0TXIFG in the IFG2 as soon after I put a data byte into the UCA0TXBUF (this is supposed to be done through s/w - manually)?. Once the byte from the UCA0TXBUF is out and it becomes empty, at that instance, Isn't the UCA0TXIFG flag set automatically? indicating that it is ready to take the next byte of data.

    2. Regarding the interrupt triggering continuously as soon as I set GIE in the code. Do you mean to say that, since at that instance in the software, the UCA0TXBUF is empty and this, in turn, keeps triggering the Tx interrupt ISR continuously setting the UCA0TXIFG flag as well?.

    3) What If I put the statement "UCA0TXBUF = 'A':" before I set the GIE and then after that I always check for the UCA0TXIFG to be set or not. if set I put the next data byte into the UCA0TXBUF. In this way, I can write a subroutine to send multiple data bytes to the serial terminal. Will this be feasible?.

    Any insights regarding the above would be helpful.

    Unsolicited: That was a good catch. I had also made a mistake with the value I had set in the UCA0BR0, it is supposed to be 0x41 i.e. 65 in decimal, for 9600 bps with a clock of 8 MHz. Thanks.

  • 1) Storing into TXBUF clears TXIFG, at least for a little while. You can explicitly clear TXIFG, but I don't recommend it (as a habit) -- rather turn off the TXIE if you have nothing to send. That leaves the TXIFG "primed" for when you have new data to send (and you just turn TXIE back on).

    2) Yes. If you don't somehow cause TXIFG to go to 0, the interrupt condition will persist and you'll just bounce right back into the ISR (forever). TXIFG is not auto-cleared by entering the ISR.

    3) You've just described "polled mode", which is also a perfectly good way to do things (advantages and disadvantages, and all that). For polled mode, don't turn on TXIE (and you can throw away the ISR).

    TI has a collection of examples for the F2274 (check the Product page), and I'm pretty sure UART --- both polled and interrupt modes --- is well covered there. I suspect if you google for "msp430 uart circular buffer" (or some such) you'll find a number of examples of how other people do interrupt mode.
  • Thanks, I have downloaded the code examples. However, I do not want to perform the write to TXBUFF inside the ISR as shown in the examples. I would like to have a separate routine which is independent of the ISR to print the string. So coming to this, I have one last question-related to the TXIFG flag in the IFG2. 

    What will be the state of the TXIFG when we copy a byte to the TXBUFF register prior to turning on the TXIE?. Something like shown in the code snippet below:

    unsigned char Uart_PrintStr(char * str_ptr) {
      int len = 0, i = 0;
      len = strlen(str_ptr);
      while (len != 0) {
        /* TXIFG is '1' in IFG2 by default */
        if ((IFG2 & 0x02) == 1) {
          /* What will happen to the TXIFG now? */
          UCA0TXBUF = str_ptr[i++];
    
          /* Turn on TXIE */
          IE2 |= UCA0TXIE;
    
          len--;
        }
      }
      /* Turn of TXIE */
      IE2 = 0x00;
    }

  • TXIFG gets set when TXBUF becomes empty (directly after a reset, or when the byte has been moved to the internal output shift register).

    When you write to TXBUF, TXIFG is cleared.

    If the UART has been idle previously, then it will begin outputting the byte immediately, and TXBUF will become free again very quickly. So in this case, it's likely that TXIFG gets set again (for the next byte).
  • So, basically, you mean to say that the setting or clearing of the TXIFG is independent of the TXIE being set or not set or completely independent of tx interrupt enable bit?.

  • Yes, TXIFG and TXIE are completely independent.

    (You get an interrupt only if both bits (and GIE) are set.)
  • Clemens Ladisch has pretty much explained everything, but to be specific:

    1) You've implemented the polled mode, which is fine; just remove the references to  TXIE, since they'll just get you in trouble.

    2) > if ((IFG2 & 0x02) == 1) {

    This condition is never true. Try:

    > if (IFG2 & 0x02) {

    or better yet:

    > if (IFG2 & UCA0TXIFG) {

  • I have been able to transmit the characters to the terminal. However, I noticed something weird i.e. Some of the characters go missing. Like for eg. If I send a string "Hello World", it prints as "Hello Wod", if the string is slightly long enough, then several characters go missing. I am not sure why this is happening. Below is the snippet I am using to print the string.

    unsigned char
    Uart_PrintStr (char *str_ptr)
    {
      int len = 0, i = 0, ret = 0;
      len = strlen (str_ptr);
      ret = len;
      while (len != 0)
        {
          while(!(IFG2 & UCA0TXIFG));
              UCA0TXBUF = str_ptr[i++];
              len--;
        }
      return (ret);
    }
    
    

    I am trying to print the string this way:

    Uart_PrintStr ("Welcome To DeeplyEmbedded!\r\n"); 

    Also, ain't using TXIE (interrupts) anymore. Any insights on this issue would be helpful. Thanks.

    PS: I am using the eZ430-RF2500 Development tool.

    
    


     

  • The code looks fine to me. I don't recall seeing this symptom with the eZ430, but it's been a while since I've used it.

    Are you still setting UCA0MCTL?

    What kind of device is at the other end of the wire?
  • Yes, I do set the UCA0MCTL. Below is my the UARTA0 register settings I do:

    static  void
    uart_configure ()
    {
      /* Register Settings */
      UCA0CTL0 = 0x00;
      UCA0CTL1 |= UCSWRST + UCSSEL_2;
      UCA0BR0 = 0x41;
      UCA0BR1 = 0x03;
      UCA0MCTL = UCBRS_1;
      UCA0CTL1 &= ~UCSWRST;
     // IE2 |= UCA0RXIE;
    }
    

    The other end is my Laptop. I just open the gtkterm, configure the port to 9600bps and run the program on the ez430.

  • Guys, any insights on troubleshooting this issue?. I need to make a release of these API's soon.

  • I don't have any equivalent equipment, so I can't try it.

    I have never had occasion to set UCA0MCTL to anything other than 0. That said, I can't claim that this would cause your symptom.
  • I tried running the device connected to another PC's USB port presuming that the issue may be loose contact, however there too the same problem persists. Changing UCA0MCTL did not work.

    After all this, I am now suspecting it to be a hardware issue or issue with the USB to UART converter chip. Hence, will try running the software on another MSP430 and check. Thanks.

  • Hi, I am back with some progress on this issue.

    I tested the program with another hardware and the same problem persisted. Then after a adding a long delay in the code, the program was able to print all the characters at a very slow rate. This fix is weird, ugly and doesn't make sense.

    I presume that may be the characters are missing because a new byte was being loaded into the TXBUF replacing the previous byte even before it could be pumped out to the terminal (UCA0TXIFG is always '0'?). Hence, after printing each character on the terminal, In the code, I gave a long delay before I wrote the next byte into the TXBUF. I tried reducing this delay further to 100 us, but then the missing character's problem re-appeared.

    Now I am certain that this isn't a hardware issue and I am not sure what is it I am doing wrong in the software. Below is the code snippet with the delay I have added to print the string.

    unsigned char
    Uart_PrintStr (char *str_ptr)
    {
      int len = 0, i = 0, ret = 0;
      len = strlen (str_ptr);
      ret = len;
      while (len != 0)
        {
          while (!(IFG2 & UCA0TXIFG));
          UCA0TXBUF = str_ptr[i++];
          len--;
          __delay_cycles (800000);
        }
      return (ret);
    }
    

    I have also attached the source code files. Please, any insights into the cause of this problem and getting this to work without the need to add the delay would be helpful. Thanks.

    msp430_codes.tar.gz 

**Attention** This is a public forum