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.

CCS/MSP-EXP430F5529LP: UART clocked via SMCLK problem

Part Number: MSP-EXP430F5529LP
Other Parts Discussed in Thread: MSP430WARE

Tool/software: Code Composer Studio

Hello,

I'm using the myUART_5529 example which can be found here: http://processors.wiki.ti.com/index.php/MSP_UART

It works very nice until I try to change the system clocks. The default speed is set to 8MHz from SMCLK. The clock configuration is as below:

#include "initclocks.h"

// ----------------------------------------------------------------------------
// myClocks.c  (for lab_04a_clock project)  ('F5529 Launchpad)
//
// This routine sets ACLK to run from REFO, then configures MCLK and SMCLK to
// run from the and high-freq internal clock source (DCO).
//
// Oscillators:
//    DCO    =   8MHz  (default is ~1MHz) Internal high-frequency oscillator
//    REFO   =  32KHz                     Internal 32KHz reference oscillator
//    MODOSC =   5MHz                     Internal 5MHz oscillator
//    VLO    = ~10KHz                     Internal very low power, low frequency oscillator
//    XT1    =  --KHz  (not configured)   External crystal input
//    XT2    =  --MHz  (not configured)   External crystal input
//
// Reference Clock:
//    FLL    = REFO   =  32KHz            Internal reference clock; used for calibrating DCO at runtime

// Internal Clocks:
//    ACLK  =  REFO   =  32KHz
//    SMCLK =  DCO    =   8MHz
//    MCLK  =  DCO    =   8MHz
//    MODCLK = MODOSC =   5MHz  (default)
// ----------------------------------------------------------------------------

//***** Defines ***************************************************************
//VLO - ~10 KHz
//REFO - 32768 Hz
//XT1 - LF:<50 KHz
//XT1 - HF: 4 MHz max
//XT2 - 4-40 MHz
//DCO - 100 KHz to CPU max
//MODOSC - 5 MHz or 5 MHz/128 used by Flash or ADC

#define LF_CRYSTAL_FREQUENCY_IN_HZ     32768                                    // 32KHz
#define HF_CRYSTAL_FREQUENCY_IN_HZ     8000000                                  // 40MHz

#define MCLK_DESIRED_FREQUENCY_IN_KHZ  8000                                     // 25MHz
#define MCLK_FLLREF_RATIO              MCLK_DESIRED_FREQUENCY_IN_KHZ / ( UCS_REFOCLK_FREQUENCY / 1024 )    // Ratio = 250

#define XT_TIMEOUT                     50000

//***** Global Variables ******************************************************
uint32_t myACLK  = 0;
uint32_t mySMCLK = 0;
uint32_t myMCLK  = 0;
uint8_t  returnValue = 0;
bool     bReturn     = STATUS_FAIL;


//***** initClocks ************************************************************
inline void initClocks(void)
{

    // Connect pins to clock crystals
    GPIO_setAsPeripheralModuleFunctionInputPin(
            GPIO_PORT_P5,
            GPIO_PIN5 +                                  // XOUT on P5.5
            GPIO_PIN4 +                                  // XIN  on P5.4
            GPIO_PIN3 +                                  // XT2OUT on P5.3
            GPIO_PIN2                                    // XT2IN  on P5.2
    );

    //    // Output the ACLK and MCLK signals to their respective pins - which allows you to
    //    // watch them with a logic analyzer (ACLK on P1.0, SMCLK on P2.2, MCLK on P7.7)
    //    GPIO_setAsPeripheralModuleFunctionOutputPin(
    //            GPIO_PORT_P1,
    //            GPIO_PIN0                                    // ACLK on P1.0   (Shared with LED1 on jumper JP8)
    //    );
    //    GPIO_setAsPeripheralModuleFunctionOutputPin(
    //            GPIO_PORT_P2,
    //            GPIO_PIN2                                    // SMCLK on P2.2  (Boosterpack - Right side (J5) pin 2)
    //    );

    //**************************************************************************
    // Configure core voltage level
    //**************************************************************************
    // Set core voltage level to handle 25MHz clock rate
    PMM_setVCore( PMM_CORE_LEVEL_3 );


    //**************************************************************************
    // Configure Oscillators
    //**************************************************************************
    // Set the XT1/XT2 crystal frequencies used on the LaunchPad, and connected
    // to the clock pins, so that driverlib knows how fast they are (these are
    // needed for the DriverLib clock 'get' and crystal start functions)
    UCS_setExternalClockSource(
            LF_CRYSTAL_FREQUENCY_IN_HZ,                                         // XT1CLK input
            HF_CRYSTAL_FREQUENCY_IN_HZ                                          // XT2CLK input
    );

    // Initialize the XT1 crystal oscillator (using a timeout in case there is a problem with the crystal)
    // - This requires P5.4 and P5.5 pins to be connected (and configured) as clock input pins.
    // - Another alternative is to use the non-timeout function which "hangs" if XT1 isn't configured;
    //    UCS_turnOnXT1( CS_XT1_DRIVE_0, UCS_XCAP_3 );   (in fact, we used the non-timeout function to setup XT2)
    // - The "WithTimeout" function used here will always exit, even if XT1 fails to initialize.
    //   You must check to make sure XT1 was initialized properly... in a real application, you would
    //   usually replace the while(1) with a more useful error handling function.
    bReturn = UCS_turnOnLFXT1WithTimeout(
            UCS_XT1_DRIVE_0,
            UCS_XCAP_3,
            XT_TIMEOUT
    );

    if ( bReturn == STATUS_FAIL )
    {
        while( 1 );
    }

    // Initializes the XT2 crystal oscillator with no timeout.
    // In case of failure, code hangs here.
    // For time-out instead of code hang use UCS_turnOnXT2WithTimeout().
    UCS_turnOnXT2(UCS_XT2_DRIVE_24MHZ_32MHZ);

    //    This is an example of turning on XT2 with the the timeout option.
    //    bReturn = UCS_turnOnXT2WithTimeout(
    //                  UCS XT2 DRIVE 4MHZ 8MHZ,
    //                  XT2_TIMEOUT
    //              );
    //
    //    if ( bReturn == STATUS_FAIL )
    //    {
    //        while( 1 );
    //    }

    // Verify if the default clock settings are as expected
    myACLK  = UCS_getACLK();
    mySMCLK = UCS_getSMCLK();
    myMCLK  = UCS_getMCLK();


    //**************************************************************************
    // Configure Clocks
    //**************************************************************************
    // Set ACLK to use REFO as its oscillator source (32KHz)
    UCS_initClockSignal(
            UCS_ACLK,                                    // Clock you're configuring
            UCS_REFOCLK_SELECT,                          // Clock source
            UCS_CLOCK_DIVIDER_1                          // Divide down clock source by this much
    );

    // Set REFO as the oscillator reference clock for the FLL
    UCS_initClockSignal(
            UCS_FLLREF,                                  // Clock you're configuring
            UCS_REFOCLK_SELECT,                          // Clock source
            UCS_CLOCK_DIVIDER_1                          // Divide down clock source by this much
    );

    // Set MCLK and SMCLK to use the DCO/FLL as their oscillator source (8MHz)
    // The function does a number of things: Calculates required FLL settings; Configures FLL and DCO,
    // and then sets MCLK and SMCLK to use the DCO (with FLL runtime calibration)
    UCS_initFLLSettle(
            MCLK_DESIRED_FREQUENCY_IN_KHZ,               // MCLK frequency
            MCLK_FLLREF_RATIO                            // Ratio between MCLK and FLL's reference clock source
    );

    //    // Optional lab step set MCLK to run from REFO
    //    // This will make the LED blink very sloooowly in our while{} loop
    //    UCS_initClockSignal( UCS_BASE,
    //            UCS_MCLK,                                    // Clock you're configuring
    //            UCS_REFOCLK_SELECT,                          // Clock source
    //            UCS_CLOCK_DIVIDER_1                          // Divide down clock source by this much
    //    );

    // Select XT2 as SMCLK source
    // We have to Re-do this call ... Why? If you use UCS_initFLLSettle() to
    //   setup MCLK, it also configures SMCLK; therefore, you should call this
    //   function after setting up MCLK
    /*UCS_initClockSignal(
            UCS_SMCLK,
            UCS_XT2CLK_SELECT,
            UCS_CLOCK_DIVIDER_1
    );*/

    // Verify that the modified clock settings are as expected
    myACLK  = UCS_getACLK();
    mySMCLK = UCS_getSMCLK();
    myMCLK  = UCS_getMCLK();
}

If I uncomment this:

UCS_initClockSignal(
            UCS_SMCLK,
            UCS_XT2CLK_SELECT,
            UCS_CLOCK_DIVIDER_1
    );

Then the UART prints garbage. I checked SMCLK via UCS_getSMCLK() call and it is returning 8000000 as expected. Without the UCS_initClockSignal() the SMCLK returns 8192000 and UART runs fine.

Strangely, if I set XT2 crystal to run at 8192000 (same as working version), it stills prints garbage. I'm missing something?

Thanks!

P.S. below is the myUART.c function:

// ----------------------------------------------------------------------------
// uart.c   ('FR6989 Launchpad)
// ----------------------------------------------------------------------------

//***** Header Files **********************************************************
#include "myUart.h"
#include "string.h"

//***** Defines ***************************************************************
//#define MYUART_IDLE    0
//#define MYUART_WRITE   1
//#define MYUART_ECHO    2

//***** Function Prototypes ***************************************************
//static unsigned char Eol( unsigned char );

//***** Global Variables ******************************************************

static unsigned short txBufLen     = 0;                                         // Number of bytes left to output; decremented as each character is sent

//---------------------------------------------------------------------------------------------
// struct Uart_t myUart;
//
// This structure defines the resources used by the UART functions of the USCI_A port.
// The typedef is found in the associated header file (myUart.h). The goal was to try and
// encapsulate the various port settings into a single structure, so as to make it easier to
// port this code to a new device.
// - Some of the fields are are defined by the device (Base Address, Number of UART channels).
// - Others are defined by the hardware board layout - in most cases, the UARTs can actually be
//   assigned to a few different Port/Pin locations.
// - Finally, there are a number of "channel variables" which are used to indicate the status
//   of the port at runtime.
//---------------------------------------------------------------------------------------------
struct Uart_t myUart = {
                         NUM_CHANNELS,                                          // Number of Uarts on the device
                         .Channels[0] = { USCI_A0_BASE,                         // Base Address of USCI_A port
                                          GPIO_PORT_P4,                         // GPIO Port settings for TX pin
                                          GPIO_PIN4,
                                          NULL,                                 // F5229 peripheral pin configuration does not have multiple SEL bits
                                          GPIO_PORT_P4,                         // GPIO Port settings for RX pin
                                          GPIO_PIN5,
                                          NULL,                                 // F5229 peripheral pin configuration does not have multiple SEL bits
                                          0,                                    // Baud Rate
                                          0,                                    // Open - UART port has been opened and configured
                                          1,                                    // TxBusy -
                                          0,                                    // TxRDY
                                          1,                                    // RxBusy
                                          0,                                    // RxRDY
                                          NOECHO                                // RxEcho
                                        },
                         .Channels[1] = { USCI_A1_BASE,                         // Base Address of USCI_A port
                                          GPIO_PORT_P3,                         // GPIO Port settings for TX pin
                                          GPIO_PIN4,
                                          NULL,                                 // F5229 peripheral pin configuration does not have multiple SEL bits
                                          GPIO_PORT_P3,                         // GPIO Port settings for RX pin
                                          GPIO_PIN5,
                                          NULL,                                 // F5229 peripheral pin configuration does not have multiple SEL bits
                                          0,                                    // Baud Rate
                                          0,                                    // Open - UART port has been opened and configured
                                          1,                                    // TxBusy -
                                          0,                                    // TxRDY
                                          1,                                    // RxBusy
                                          0,                                    // RxRDY
                                          DOECHO                                // RxEcho
                                        }
                       };

// The following structure will configure the USCI_A port to run at 9600 baud from an 8MHz SMCLK
// The baud rate values were calculated at: software-dl.ti.com/.../index.html
USCI_A_UART_initParam myUart_Param_9600_8N1_SMCLK8MHz = {
    USCI_A_UART_CLOCKSOURCE_SMCLK,
    52,                                                                         // clockPrescalar
    1,                                                                          // firstModReg
    0,                                                                         // secondModReg
    USCI_A_UART_NO_PARITY,
    USCI_A_UART_LSB_FIRST,
    USCI_A_UART_ONE_STOP_BIT,
    USCI_A_UART_MODE,
    USCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION
};

// The following structure will configure the USCI_A port to run at 115200 baud from an 8MHz SMCLK
// The baud rate values were calculated at: software-dl.ti.com/.../index.html
USCI_A_UART_initParam myUart_Param_115200_8N1_SMCLK8MHz = {
    USCI_A_UART_CLOCKSOURCE_SMCLK,
    4,                                                                         // clockPrescalar
    3,                                                                          // firstModReg
    5,                                                                         // secondModReg
    USCI_A_UART_NO_PARITY,
    USCI_A_UART_LSB_FIRST,
    USCI_A_UART_ONE_STOP_BIT,
    USCI_A_UART_MODE,
    USCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION
};

// The following structure will configure the USCI_A port to run at 9600 baud from an 32KHz ACLK
// The baud rate values were calculated at: software-dl.ti.com/.../index.html
USCI_A_UART_initParam myUart_Param_9600_8N1_ACLK32Kz = {
    USCI_A_UART_CLOCKSOURCE_ACLK,
    3,                                                                          // clockPrescalar
    0,                                                                          // firstModReg
    3,                                                                        // secondModReg
    USCI_A_UART_NO_PARITY,
    USCI_A_UART_LSB_FIRST,
    USCI_A_UART_ONE_STOP_BIT,
    USCI_A_UART_MODE,
    USCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION
};

//*****************************************************************************
// myUart_init()
//
// Initialize the UART functionality of the USCI peripheral
// - The "myUart_Instance" parameter allows the user to setup any of the UARTs
//   (Two UARTS are available on the 'FR6989)
// - This function verifies that the DriverLib UART init function returns
//   successfully
// - Waiting for the UART to send data can be done with either "polling" or
//   "interrupts"; this init routine enables the USCI UART interrupts
//*****************************************************************************
int myUart_init( uint16_t myUart_Instance, uint32_t BaudRate, USCI_A_UART_initParam *param )
{
    // Get this channel's USCI's base address from myUart structure
    uint16_t BaseAddr = myUart.Channels[myUart_Instance].BaseAddress;

    // Abort and return an error if the channel has already been initialized
    if( myUart.Channels[myUart_Instance].Open )
        return( STATUS_ALREADY_OPEN );

    // Initialize the UART using one of the two sets of parameters provided (or modify the parameters above to meet your needs)
    if( STATUS_FAIL == USCI_A_UART_init( BaseAddr, param ))
        return( STATUS_INIT_FAILED );

    // Baud rate retained for future clock adjustment function
    myUart.Channels[myUart_Instance].BaudRate = BaudRate;

    // Enable (i.e. turn on) the UART
    USCI_A_UART_enable( BaseAddr );

    // Set the status flags for this instance of our UART channel
    myUart.Channels[myUart_Instance].Open = 1;                                  // Indicate the port has been opened and initialized
    myUart.Channels[myUart_Instance].TxBusy = 0;                                // Set TX port to "not busy" (since we are not actively sending data, yet)
    myUart.Channels[myUart_Instance].RxBusy = 0;                                // Set RX port to "not busy" (since we are not actively receiving data, yet)
    myUart.Channels[myUart_Instance].TxRDY = 1;                                 // TX port is ready by default, since the transmit buffer is empty)
    myUart.Channels[myUart_Instance].RxRDY = 0;                                 // RX port is not ready by default, as there's nothing yet to read

    // Return successful, if we made it this far
    return( STATUS_INIT_SUCCESSFUL );
}


//*****************************************************************************
// myUart_writeBuf()
//
// Configures UART to send a buffer of data
// - The USCI_A_UART_transmitData() DriverLib function handles sending one
//   byte of data, whereas this function will send an entire buffer
// - This is a 'blocking' function - that is, it does not exit until the whole
//   buffer has been sent; rather than a wait-loop, though, this function waits
//   using LPM0 (and the transmit interrupt)
// - If the UART is not busy sending data already, this function sends the
//   first byte of data, then lets the UART ISR send the rest of the data
//
// Parameters
// - myUart_Instance:  Let's you select which UART to send the buffer; no error
//                     checking is done, as it is assumed you successfully
//                     initialized the UART
// - *txBuf:           Buffer of data to be written to UART port; function
//                     checks that the buffer does not have a NULL address
// - BufLen:           How many bytes do you want to send (you don't have to
//                     send the whole buffer which was passed). If a value of
//                     zero is passed, the function will calculate the buffer
//                     length for you
// - doCrLf:           Do you want to send a Carriage Return and Linefeed
//                     after the data buffer has been sent? (1 Yes; 0 N0)
// - Return:           This function returns the number of characters sent
//*****************************************************************************
int myUart_writeBuf( uint16_t myUart_Instance, unsigned char *txBuf, uint16_t BufLen, int DoCrLf )
{
    uint16_t BaseAddr = myUart.Channels[myUart_Instance].BaseAddress;           // Get this channel's USCI's base address from myUart structure
    unsigned char out = 0;
    int ret = -1;                                                               // Variable which will hold return value for this function

    // Exit if there is no transmit buffer
    if( txBuf == NULL )
        return( STATUS_FAIL_NOBUFFER );

    // Exit the function if we're already busy writing, else set the 'busy' flag
    if ( myUart.Channels[myUart_Instance].TxBusy )
        return( STATUS_FAIL_BUSY );
    else
        myUart.Channels[myUart_Instance].TxBusy = 1;

    // Check if the transmit length was provided as a parameter; if it's zero,
    // calculate the size of the buffer (i.e. number of chars to transmit)
    if ( BufLen == 0 )
        txBufLen = strlen( (const char *)txBuf );
    else
        txBufLen = BufLen;

    // Add to transmit length for carriage return (enter) and linefeed, if requested by user
    if ( DoCrLf )
    {
        txBufLen += 2;
    }

    // Since 'txBufLen' is decremented during transfers, retain the original value
    ret = txBufLen;

    // Enable USCI_Ax TX interrupt
    USCI_A_UART_enableInterrupt( BaseAddr, USCI_A_UART_TRANSMIT_INTERRUPT);

    // Keep sending characters until complete
    while( txBufLen >> 0 )
    {
        if ( myUart.Channels[myUart_Instance].TxRDY == 1 )                      // Check if TX port is ready (if we got here, it should be ready)
        {
            myUart.Channels[myUart_Instance].TxRDY = 0;                         // Clear the ready bit now that we're planning to send a byte

            out = *txBuf;                                                       // Read from buffer (note that this reads past end of buffer if we're doing CRLF)
            txBuf++;                                                            // Move buffer pointer to next item to be sent

            if ( DoCrLf ) {                                                     // If doing CRLF, replace 'out' with the CR or LF
                if ( txBufLen == 2 )
        		    out = ASCII_LINEFEED;
        	    else if ( txBufLen == 1 )
        		    out = ASCII_ENTER;
            }

            txBufLen--;                                                         // Decrement the transmit count

            USCI_A_UART_transmitData( BaseAddr, out );                         // Send the data to the transmit port
            if ( myUart.Channels[myUart_Instance].TxRDY == 0 )                  // Test TxRDY to help prevent race condition where interrupt occurs before we reach this step
                __low_power_mode_0();                                           // Sleep CPU until woken up by transmit ready interrupt event
        }                                                                       // (other LPMx modes could be used, depending upon clock requirements)
    }

    // Disable the UART transmit interrupt
    USCI_A_UART_disableInterrupt( BaseAddr, USCI_A_UART_TRANSMIT_INTERRUPT);

    // Return the length of the string that was sent
    return (int) ret;
}


//*****************************************************************************
// myUart_readBuf()
//
// This function receives a buffer of data via the UART. This is a blocking
// function, thus it will not return until the full length has been received.
//
// Parameters:
// - myUart_Instance:  Let's you select which UART should recieve the buffer;
//                     no error checking is done, as it is assumed you
//                     successfully initialized the UART
// - *rxBuf:           Buffer that the received data should be written into;
//                     this function checks that the buffer doesn'tt have a
//                     NULL address (if so, it exits
// - *rxSize:          How many bytes do you want to receive; a default size
//                     of 1 line (80 bytes) is used if a "0" is passed;
//                     Note that receiving a carriage return or linefeed will
//                     force the function to stop receiving data, even if the
//                     'Length' of bytes has not yet been received;
//                     Finally, we used a pointer for the size so that the
//                     actual number of received bytes is returned
// - Return:           The status of the function
//*****************************************************************************
int myUart_readBuf( uint16_t myUart_Instance, unsigned char *rxBuf, uint16_t *rxSize )
{
  uint16_t BaseAddr = myUart.Channels[myUart_Instance].BaseAddress;             // Check if TX port is ready (if we got here, it should be ready)
  unsigned int  ret      = STATUS_INIT_SUCCESSFUL;                              // Variable to hold function status (initialize as 'successful')
  unsigned int  i        = 0;                                                   // Local variable used in 'for' loop
  unsigned char in[3]    = { 0, 0, 0 };                                         // Temporary variable to hold received data (only 1 byte will be used for rec'd data; extra locations to add CRLF)
  uint8_t       inLen    = 0;                                                   // Current length of "in" array
  uint16_t      rxBufLen = 0;                                                   // Current length of input buffer

    // Exit if there is no read buffer
    if( rxBuf == NULL )
        return( STATUS_FAIL_NOBUFFER );

    // Exit the function if we're already busy reading, else set the 'busy' flag
    if ( myUart.Channels[myUart_Instance].RxBusy )
        return( STATUS_FAIL_BUSY );
    else
        myUart.Channels[myUart_Instance].RxBusy = 1;

    // If '0' is passed as the "number of bytes to read", set to default size
    if ( *rxSize == 0 )
        *rxSize = DEFAULT_MAX_READ;

    // If recieve "echo" feature is enabled, wait until the transmit channel isn't busy
    if ( myUart.Channels[myUart_Instance].RxEcho ) {
        if ( myUart.Channels[myUart_Instance].TxBusy == 1 )
        {
            __low_power_mode_0();
        }
    }

    // Clear and enable USCI_Ax RX interrupt
    USCI_A_UART_clearInterrupt( BaseAddr, USCI_A_UART_RECEIVE_INTERRUPT);
    USCI_A_UART_enableInterrupt( BaseAddr, USCI_A_UART_RECEIVE_INTERRUPT);

    // Keep transmitting until the receive data buffer has reached the specified rxSize
    while ( rxBufLen < *rxSize )
    {
        // We 'missed' reading the data in time if RxRDY ever goes above '1'
        if ( myUart.Channels[myUart_Instance].RxRDY >> 1 )
            ret = STATUS_RX_MISSED_REAL_TIME;

        // If not ready, sleep until we get a receive interrupt event that sets the RxRDY flag
        if ( myUart.Channels[myUart_Instance].RxRDY == 0 ) {
            __low_power_mode_0();
        }
        else {
            myUart.Channels[myUart_Instance].RxRDY = 0;                         // If Rx is ready, clear the ready bit
            in[0] = USCI_A_UART_receiveData( BaseAddr );                       // Read byte from the RX receive buffer
            inLen = 1;                                                          // Set 'in' buffer length to '1' byte

            // If input byte is CR (or linefeed) add the other character to 'in'
            switch ( in[0] )
            {
                case ASCII_LINEFEED:
                    in[1] = ASCII_ENTER;
                    inLen++;                                                    // Increment the size of 'in' buffer length
                    *rxSize = rxBufLen;                                         // Set receive size to current buffer length to force the function to complete
                    break;

                case ASCII_ENTER:
                    in[1] = ASCII_LINEFEED;
                    inLen++;                                                    // Increment the size of 'in' buffer length
                    *rxSize = rxBufLen;                                         // Set receive size to current buffer length to force the function to complete
                    break;
            }

            // Copy 'in' character(s) to the data receive buffer
            for ( i = 1; i <= inLen; i++ ) {
                *( rxBuf + rxBufLen ) = in[i-1];
                rxBufLen++;
            }

           // If 'echo' is enabled, trasmit the newly received character(s) back to sender (for terminals without 'local echo')
           if ( myUart.Channels[myUart_Instance].RxEcho ) {
                if ( !myUart.Channels[myUart_Instance].TxBusy )                 // Wait until transmit isn't busy, before sending character(s)
                {
                    myUart_writeBuf( CHANNEL_1, (unsigned char *)in, inLen, NOCRLF );
                }
            }
        }
    }

    // Disable the RX interrupt and set the port to 'not busy'
    USCI_A_UART_disableInterrupt( BaseAddr, USCI_A_UART_RECEIVE_INTERRUPT);
    myUart.Channels[myUart_Instance].RxBusy = 0;

    // Return with status
    return ( ret );
}


/*//*****************************************************************************
// USCI_A0 Interrupt Service Routine
//*****************************************************************************
#pragma vector = USCI_A0_VECTOR
__interrupt void myUart0_isr(void)
{
	int chan = 0;

    switch ( __even_in_range( UCA0IV, USCI_UCTXIFG ))
    {
        case USCI_NONE:
        	break;

        // UART receive interrupt
        case USCI_UCRXIFG:

            myUart.Channels[chan].RxRDY++;                                      // Interrupt tells us that that the UART RX buffer is ready to read
            break;

        // UART transmit interrupt
        case USCI_UCTXIFG:

            myUart.Channels[chan].TxRDY = 1;                                    // Interrupt tells us that that the UART TX buffer is available for writing
            if ( txBufLen == 0 )
                myUart.Channels[chan].TxBusy = 0;                               // Set the Tx as 'not busy' if full buffer has been transfered
            break;
//
//        case USCI_UART_UCSTTIFG:
//            __no_operation();
//            break;
//
//        case USCI_UART_UCTXCPTIFG:
//            __no_operation();
//            break;
    }

    // Exit low-power mode:
    //   Now that we either have received a byte - or are ready to transmit
    //   a another byte - we need to wake up the CPU (since our read/write
    //   routines enter LPM while waiting for the UART to do its thing)
    _low_power_mode_off_on_exit();

}*/

//*****************************************************************************
// USCI_A1 Interrupt Service Routine
//*****************************************************************************
#pragma vector = USCI_A1_VECTOR
__interrupt void myUart1_isr(void)
{
	int chan = 1;

    switch ( __even_in_range( UCA1IV, USCI_UCTXIFG ))
    {
        case USCI_NONE:
        	break;

        // UART receive interrupt
        case USCI_UCRXIFG:

            myUart.Channels[chan].RxRDY++;                                      // Interrupt tells us that that the UART RX buffer is ready to read
            break;

        // UART transmit interrupt
        case USCI_UCTXIFG:

            myUart.Channels[chan].TxRDY = 1;                                    // Interrupt tells us that that the UART TX buffer is available for writing
            if ( txBufLen == 0 )
                myUart.Channels[chan].TxBusy = 0;                               // Set the Tx as 'not busy' if full buffer has been transfered
            break;
//
//        case USCI_UART_UCSTTIFG:
//            __no_operation();
//            break;
//
//        case USCI_UART_UCTXCPTIFG:
//            __no_operation();
//            break;
    }

    // Exit low-power mode:
    //   Now that we either have received a byte - or are ready to transmit
    //   a another byte - we need to wake up the CPU (since our read/write
    //   routines enter LPM while waiting for the UART to do its thing)
    _low_power_mode_off_on_exit();

}

  • Hi Helder,
    Did you change your XT2? If not, you are using the wrong values, as it is a 4 MHz Resonator. This may be causing your baudrate to change, hence making the UART output appear as garbage.
  • Hi Cameron,

    Yes, or I believe so. I used this function:

    UCS_setExternalClockSource(
                LF_CRYSTAL_FREQUENCY_IN_HZ,                                         // XT1CLK input
                HF_CRYSTAL_FREQUENCY_IN_HZ                                          // XT2CLK input
        );

    Where HF_CRYSTAL_FREQUENCY_IN_HZ is set at 8000000. Also, did that:

    UCS_initClockSignal(
                UCS_SMCLK,
                UCS_XT2CLK_SELECT,
                UCS_CLOCK_DIVIDER_1
        );
    

    UCS_getSMCLK() is returning 8MHz, from what I understood this returns the current value set to crystal. But when I do not initialize the clock signal (meaning the XT2CLK be the same as CPU's), everything works fine. Tried with several frequencies up to 40MHz, none of them works (setting the prescalar and the required settings according to this webpage http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html.

  • Helder,
    This is something you would have to physically change, ie, solder a new crystal into place. The function returns register contents, not a measured frequency of the crystal. My guess is that if you observed the signal it would still be 4MHz, or not running at all. Do you have any XT fault flags showing?
  • Hi Cameron,

    I'm not sure how to do that. It is one of the following entries?

    Also, seeing from the device's user guide, I found that XT2 is a 4MHz ceramic ressonator. So, to achieve 8MHz previously set (the working one), it is using FLL? My limit then would be 25MHz?

  • The fault flags are documented in section 5.2.12 of the User's Guide. See UCSCTL7.

    But what are you going to do with an 8 MHz clock? What is the actual problem you're trying to solve?

  • Actually I want the highest clocks possible, 8MHz was initially the only clock that worked. I plan to communicate with Tiva123 via UART at 115200 or 921600 baud rate (managed with the "default" example). For now it's mostly just to learn more about the MSP, I'm pretty new to this platform.

    I got confused by the workshop saying that could be clocked from 4MHz to 40MHz. But it seems that either I change the crystal (maybe use an digital oscillator signal) or use the FLL to rise the clock up to ~25MHz.

  • If you are looking for fast transfer, UART on MSP430 can go over 1 Mbps. I done some benchmark.

    For setup, you can use my attached calculator.

    7585.MSP430UartCalc.rar

  • Well, I don't know to program with registers. I've the basiest of basics of knowledge to program in that way. But, at least I've managed to make it work properly at 115200 with SMCLK of 4MHz (the backchannel one)!

    Rising up SMCLK to 20MHz using XT2 as FLL reference didn't prove useful, 921600 still printing garbage. But at least I've a usable baud rate (115200) and lower power consumption.

    Since you've showed that MSP430 can go over 1Mbps, I think I'll use the other UART module or abandon backchannel...
  • Helder Sales said:

    Since you've showed that MSP430 can go over 1Mbps, I think I'll use the other UART module or abandon backchannel...

    iF I remember right, LP backchannel is limited to 1 Mbps. Also, if you need hi speed communication between MSP / PC than USB CDC can be used, that can go up to 1 MByte / s.

  • Maybe MSP430Ware or the example has its faults (i.e. not optimized). I'm considering learning the "traditional" approach, that may be the solution. And thanks for the suggestion, I'll take a look at that.
  • Do you still need help implementing the 921600 baud, or is this solved by the 115200?
  • Hi Cameron,

    Yes, I can work with 115200 without problems, 921600 isn't mandatory. When I have time, I'll look on how to set UART at 921600 properly, for now I'll focus dealing with the MSP430Ware API calls.

    By the way, the application example provided in this link (for 'F5529LP) has two main flaws:

    In myUart.c, on this part

    struct Uart_t myUart = {
                             NUM_CHANNELS,                                          // Number of Uarts on the device
                             .Channels[0] = { USCI_A0_BASE,                         // Base Address of USCI_A port
                                              GPIO_PORT_P4,                         // GPIO Port settings for TX pin
                                              GPIO_PIN4,
                                              NULL,                                 // F5229 peripheral pin configuration does not have multiple SEL bits
                                              GPIO_PORT_P4,                         // GPIO Port settings for RX pin
                                              GPIO_PIN5,
                                              NULL,                                 // F5229 peripheral pin configuration does not have multiple SEL bits
                                              0,                                    // Baud Rate
                                              0,                                    // Open - UART port has been opened and configured
                                              1,                                    // TxBusy -
                                              0,                                    // TxRDY
                                              1,                                    // RxBusy
                                              0,                                    // RxRDY
                                              NOECHO                                // RxEcho
                                            },
                             .Channels[1] = { USCI_A1_BASE,                         // Base Address of USCI_A port
                                              GPIO_PORT_P3,                         // GPIO Port settings for TX pin
                                              GPIO_PIN4,
                                              NULL,                                 // F5229 peripheral pin configuration does not have multiple SEL bits
                                              GPIO_PORT_P3,                         // GPIO Port settings for RX pin
                                              GPIO_PIN5,
                                              NULL,                                 // F5229 peripheral pin configuration does not have multiple SEL bits
                                              0,                                    // Baud Rate
                                              0,                                    // Open - UART port has been opened and configured
                                              1,                                    // TxBusy -
                                              0,                                    // TxRDY
                                              1,                                    // RxBusy
                                              0,                                    // RxRDY
                                              DOECHO                                // RxEcho
                                            }
                           };

    the pins are assigned to the wrong channels (also wrong pins i.e. P3.5), it is no immediate problem as the program initialize all the UART pins, but if you try to init only one of the UARTs, this might be a issue.

    The other problem is, when you read the buffer via myUart_readBuf(), if you set the *rxsize and input something smaller on the console (or via rx pin) and press "enter" (or send "\r\n"), the rxsize you set will be replaced by the string length that was received. Not sure if I made myself clear, so I'll give an example:

    static uint8_t size = 0; //size of 0 means that the function will assign the defaut value of 80
    
    UARTreadBuf(CHANNEL_1,(unsigned char *)val, &size);  //do not return until full or CRLF
    
    //let's say you typed "LED ON"
    
    //do the things with the string "LED ON"
    
    UARTreadBuf(CHANNEL_1,(unsigned char *)val, &size); //try to input "LED OFF"

    In this example, the UARTreadBuf() will return BEFORE you type "LED OFF". Because when you typed "LED ON", the *rxsize replaced the value you assigned to size with the length of the string "LED ON", which is 6 in this case. You'll only be able to type "LED OF".

    My solution to this problem was removing the "*" operator, making myUart_readBuf(uint16_t myUart_Instance, unsigned char *rxBuf, uint16_t rxSizeinstead of  uint16_t *rxSize. Then the size doesn't change accordinly to the receive buffer.

    Not sure where to give feedback about this, but these are my findings.

    Thanks for your concern btw!

  • Thanks Helder,
    I'll make sure this feed back gets to the appropriate person.

**Attention** This is a public forum