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/MSP430FR5969: Debug expressions read 0xFF always

Part Number: MSP430FR5969
Other Parts Discussed in Thread: MSP430WARE,

Tool/software: Code Composer Studio

Debugging expressions always read 0xFF (eg, the variables respective maximums depending on the data type).

The programs do not work as intended, as if the variables are in fact at their maximums.

Without debugging the whole thing seems to work as intended.

The whole thing used to work, suddenly does not work anymore. Updated to CCS 7.3, problem still remains.

Problem occures also with the simple examples directly out of tirex.

In this case msp430fr59xx_lpm3-5_02.c which always sets the LED to light up because ledstate always reads 0xFF while debugging.

Without debugging the LED seems to flash even though it should not - eg. the LED goes off while the MSP is in LPM3.5 which i think it should not.

(Thus it may be possible that it still reads 0xFF but goes only off while in LPM3.5 and on bootup again restores it to 0xFF...?)

Am I doing anything wrong? Any advice is welcome.

For your reference the lpm3.5 sample directly out of tirex:

/* --COPYRIGHT--,BSD_EX
 * Copyright (c) 2012, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *******************************************************************************
 *
 *                       MSP430 CODE EXAMPLE DISCLAIMER
 *
 * MSP430 code examples are self-contained low-level programs that typically
 * demonstrate a single peripheral function or device feature in a highly
 * concise manner. For this the code may rely on the device's power-on default
 * register values and settings such as the clock configuration and care must
 * be taken when combining code from several examples to avoid potential side
 * effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware
 * for an API functional library-approach to peripheral configuration.
 *
 * --/COPYRIGHT--*/
//******************************************************************************
//   MSP430FR59xx Demo - RTC_B in LPM3.5 with 2 second wake-up interval
//
//   Description: The RTC_B module is in counter mode with counter interrupt
//   triggers every 2 seconds. The device will then enter LPM3.5 waiting for
//   RT1PSIFG interrupt. Upon wake-up from LPMx.5, the device restores the
//   previous state of P1.0 LED based on the ledState variable. It then toggles
//   the P1.0 LED on the board and stores the LED state into FRAM memory 0x4400.
//   This is a good example to demonstrate how to save the GPIO state before
//   entering LPMx.5 and restoring the GPIO state upon wake-up.
//   P4.6 is used as a heartbeat showcasing that the device is either waking
//   up from a BOR reset or LPMx.5.
//
//   ACLK = 32.768kHz, MCLK = SMCLK = DCO = ~1MHz
//
//               MSP430FR59xx
//             -----------------
//         /|\|              XIN|-
//          | |                 | 32kHz
//          --|RST          XOUT|-
//            |                 |
//            |             P1.0|--> LED
//            |             P4.6|--> Probe out/LED
//
//   William Goh
//   Texas Instruments Inc.
//   January 2013
//   Built with Code Composer Studio v5.5 and Embedded Workbench v5.60
//******************************************************************************
#include <msp430.h>

void initBoard(void);
void initRtc(void);
void WakeUpLPM35(void);

// Stores the state of the LED in FRAM where this variable
// is not C-initialized during start-up. This allows
// certain variables to easily be restored and managed
// in a non-volatile memory with no flash charge-pump required.
// This allows faster start-up time.
#if defined(__TI_COMPILER_VERSION__)
#pragma NOINIT(ledState);
#pragma location=0x4400
unsigned char ledState;
#elif  defined(__IAR_SYSTEMS_ICC__)
__persistent unsigned char ledState;
#else
// For other compilers, insert this variable into FRAM memory
unsigned char ledState;
#endif

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;               // Stop WDT

    // Initialize board
    initBoard();                            // Regular init code for GPIO and CS

    // Determine whether we are coming out of an LPMx.5 or a regular RESET.
    if (SYSRSTIV == SYSRSTIV_LPM5WU)
    {
        // When woken up from LPM3.5, reinit
        WakeUpLPM35();                      // LPMx.5 wakeup specific init code
        __enable_interrupt();               // The RTC interrupt should trigger now...
    }
    else
    {
        ledState = 0;                       // Initialize LED state variable
        P1OUT = 0x00;                       // For initialize P1OUT to zero initially
        initRtc();                          // Regular init code for RTC_B
    }

    // Use P4.6 LED as a heart beat for to represent device restarted either
    // from LPMx.5 or a complete power-up
    P4OUT |= BIT6;

    // Use Timer A for a short delay to blink P1.0 LED
    TA0CCTL0 = CCIE;                        // TACCR0 interrupt enabled
    TA0CCR0 = 1000;
    TA0CTL = TASSEL__ACLK | MC__UP;         // SMCLK, UP mode
    __bis_SR_register(LPM3_bits | GIE);
    TA0CTL &= ~(MC__UP);                    // Stop Timer

    P4OUT &= ~BIT6;                         // Clear P4.6 LED

    // Sequence to enter LPM3.5.
    PMMCTL0_H = PMMPW_H;                    // Open PMM Registers for write
    PMMCTL0_L |= PMMREGOFF;                 // and set PMMREGOFF

    // Enter LPM3.5 mode with interrupts enabled. Note that this operation does
    // not return. The LPM3.5 will exit through a RESET event, resulting in a
    // re-start of the code.
    __bis_SR_register(LPM3_bits | GIE);
    __no_operation();

    return 1;
}

void initBoard(void)
{
    // Port Configuration
    // Restore P1.0 LED state before reset from a variable
    // stored in FRAM
    P1OUT = ledState;
    P1DIR = 0xFF;
    P2OUT = 0x00;
    P2DIR = 0xFF;
    P3OUT = 0x00;
    P3DIR = 0xFF;
    P4OUT = 0x00;
    P4DIR = 0xFF;
    PJOUT = 0x00;
    PJSEL0 |= BIT4 | BIT5;
    PJDIR = 0xFFFF;

    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;

    // Setup Clocks
    CSCTL0_H = CSKEY >> 8;                  // Unlock CS registers
    CSCTL1 = DCOFSEL_0;                     // Set DCO to 1MHz
    CSCTL2 = SELA_0 | SELS_3 | SELM_3;      // set ACLK = XT1; MCLK = DCO
    CSCTL3 = DIVA_0 | DIVS_0 | DIVM_0;      // Set all dividers to 1
    CSCTL4 &= ~LFXTOFF;                     // Enable LFXT1

    do
    {
        CSCTL5 &= ~LFXTOFFG;                // Clear XT1 fault flag
        SFRIFG1 &= ~OFIFG;
    } while (SFRIFG1 & OFIFG);              // Test oscillator fault flag
    CSCTL0_H = 0;                           // Lock CS registers
}

void initRtc(void)
{
    // Configure RTC_B
    // Configure BCD mode, stop the RTC, and enable RTC
    RTCCTL01 = RTCBCD | RTCHOLD | RTCTEV_0;
    // Set the RTC second stage divider to 256
    // RTC interrupts every 2 seconds
    RTCPS1CTL = RT1IP_7 | RT1PSIE;

    // Start RTC calendar mode
    RTCCTL01 &= ~RTCHOLD;
}

void WakeUpLPM35(void)
{
    // Re-configure / start RTC
    // Configure BCD mode, stop the RTC, and enable RTC
    RTCCTL01 |= RTCBCD | RTCHOLD | RTCTEV_0;
    // Set the RTC second stage divider to 256
    // RTC interrupts every 2 seconds
    RTCPS1CTL = RT1IP_7 | RT1PSIE;

    // Start RTC calendar mode
    RTCCTL01 &= ~RTCHOLD;
}


#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=RTC_VECTOR
__interrupt void RTC_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void)
#else
#error Compiler not supported!
#endif
{
    switch (__even_in_range(RTCIV, RTCIV_RTCOFIFG))
    {
        case RTCIV_NONE:      break;
        case RTCIV_RTCRDYIFG: break;
        case RTCIV_RTCTEVIFG: break;
        case RTCIV_RTCAIFG:   break;
        case RTCIV_RT0PSIFG:  break;
        case RTCIV_RT1PSIFG:
            // Toggle the LED on P1.0
            P1OUT ^= BIT0;

            // Store P1.0 output state to a variable
            ledState = (P1OUT & BIT0);
            break;
        case RTCIV_RTCOFIFG: break;
    }
}

// Timer A0 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer_A (void)
#else
#error Compiler not supported!
#endif
{
    __bic_SR_register_on_exit(LPM4_bits);
}

  • Hi Daniel,

    It looks like you are using an older version of the code example msp430fr59xx_lpm3-5_02.c. If I use the version from the latest MSP430Ware version 3.80 or if I use the version from the ti.com product folder here: www.ti.com/.../slac536 Then I see that it uses #pragma PERSISTENT to place the variable in FRAM, not "location". The problem in this case is that the FRAM is protected by the MPU tool built into newer versions of CCS by default. When you use #pragma PERSISTENT to place the variable in FRAM, this allows the compiler and linker file to know automatically that there is a variable in FRAM and adjust the FRAM partitioning accordingly - this is the right way to do it because it prevents conflicts as you could see using "location" with a hard-coded address because that would require a customized MPU setup. This is why the code examples were brought up-to-date to use PERSISTENT now that we have this MPU protection enabled by default in newer versions of CCS and IAR.

    Can you try the newer version of the code example and report back?

    Regards,
    Katie

  • Thank you Katie, this has fixed my problems.
    In fact I do have some trouble understanding the differences or use cases of #pragma PERSISTENT, NOINIT or the DATA_SECTION.

    Which one is to be picked for storing UART updatable parameters which have to survive LPM3.5?
  • Hi Daniel,

    If you want to place variables in FRAM so that they are retained through power-cycles or LPMx.5 events, then the right way to do it is to use #pragma PERSISTENT.

    Here's what happens behind the scenes: If you look in the linker file for your device, lnk_msp430fr5969.cmd in your project, you can see that there is a section called .TI.persistent. Every variable that you mark with #pragma PERSISTENT will be placed in this .TI.persistent section instead of the normal .bss or .data sections that are placed in RAM. You can see that .TI.persistent is placed at the beginning of FRAM at address 0x4400 in a group called "READ_WRITE_MEMORY". Basically what is happening is that the linker file is grouping all data that should go in FRAM with read + write access, vs code that should go in FRAM with read + execute access (no write). It does this so that the MPU can be automatically configured by the tool to set the separate permissions for different segments of FRAM as read + write access vs read + execute access. Notice also how the section .TI.noinit is by default placed in RAM, which means it won't be retained through LPMx.5 modes.

    Using DATA_SECTION or "location" places variables in specific locations, but they are more general pragmas than PERSISTENT - basically PERSISTENT is special and was created just for putting things in read + write FRAM. Whereas DATA_SECTION could be used to put data in any section that's defined in the linker file (whichever one you specify). You could for example use #pragma DATA_SECTION (x, ".TI.persistent") to basically do the same thing as just using #pragma PERSISTENT, or you could used DATA_SECTION to place x somewhere else like in .data or in a section you define yourself if you modified your linker file. Using "location" specifies a hard-coded address for something, but usually it would be preferred to let the linker file place things to avoid any conflicts.

    Because PERSISTENT is used for placing data in FRAM, which is non-volatile, it also means that the variables will only be loaded with their default value once at program load - after that, on successive start-ups/resets the c-startup code will not re-initialize the variable because since it is non-volatile it should still retain its last value. This prevents retained data from getting over-written. In that sense, PERSISTENT is similar to NOINIT except that it has a defined default value for when you first load the device (basically it will have a value that gets written with the binary code image).

    I hope this helps to make things a little bit clearer rather than confusing things further - please let me know if you have some follow-up questions and I can try to explain more.

    Regards,
    Katie

**Attention** This is a public forum