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.

MSP430FR2355: Why is my application restarting?

Part Number: MSP430FR2355

So I have the main body of my software running in a loop. The loop keeps going for awhile. For this conversation it is pretty much an infinite loop. 

before the loop occurs its really just setting up TimerB, RTC, and GPIO pins. 

Once we hit the loop this is the flow

if usb connected AND !burst_cycle
          Enter menu mode
else if !usb connected AND burst_cycle
          disable burst_cycle
else if !burst_cycle
          prep 4 LPM
          if !usb connected AND lpm time hasn't been met
                    enter LPM
                    exit LPM
                    calculate time in LPM and add to system time
          wake up
          if usb connected AND !burst_cycle
                     restart at beginning of loop
prep for scan
scan for predetermined period of time or until !usb connected
end scan functionatlity
start at beginning of loop

and here is the actual code of the loop itself. 

while (localrecord < 0xFFFF)  //FFFF is the last record possible on the disk
    {

        // checks to see if a USB cable is connected to the device, but not in terminal_debug.
        if ((P2IN & BIT4) && !BURST_CYCLE)
        {

            run_menu();

            continue;
        }
        else if( !(P2IN & BIT4) && BURST_CYCLE)
        {

            BURST_CYCLE = 0;
            continue;
        }
        // Normal operation when the USB cable is connected or disconnected, but has exited the main menu and not in terminal debug mode.
        else if (!BURST_CYCLE)
        {

            prep_4_sleep();

            while ( !(P2IN & BIT4) && (lpm_count < lpm_multiplier) )
            {

                enter_low_power_mode();
                calc_sys_time(lpm_period);
                lpm_count++;

            }

            lpm_count = 0;

            wake_up();

            delay_ms(500);

            if ((P2IN & BIT4) && !BURST_CYCLE)
                continue;

        }

        prep_scan();

        start_read = time2Sec();

        readFlag = 1;

        do
        {

            read_sensor();
            if( readFlag)
                readFlag = counter(start_read, READTIME);

            if( !(P2IN & BIT4) && (numOfComReads == 1) )
                break;

        }while (readFlag || (numOfComReads != 1) );

        end_scan();
    }

What I'm seeing is at random times the application itself is resetting. It will be running just fine and then it starts all over from the beginning of the Main method. 

Now I know that the software examples for LPM doesn't use a loop, rather it will enter LPM for the predetermined time, exit and the main menu restarts itself. It was predetermined, by someone not me, that they wanted to implement the software by utilizing a loop. Rather than the using the auto restart aspect of the chip. 

How do I keep the software from relaunching from the beginning of the main method? 

Keep in mind, I thought that it was exciting the while loop, so I threw a break point outside of the while loop and its never tripped. 

Now that I think of it, I'm pretty sure that its not restarting from the beginning of the Main Method rather reloading the entire software package. Am I correct on that?

  • What does SYSRSTIV say? [Ref Data Sheet (SLASEC4B) Table 6-12]

  • Hey Bruce, 

    SYSRSTIV is set to a value of 0x0002.

    Looking at Table 6-12 of the MSP430FR2355 data sheet. It shows that 02h is a Brownout event  (BOR) . 

    So looking up BOR I found a definition of 

    intentional or unintentional drop in voltage in an electrical power supply.

    Forgive me, when the register SYSRSTIV is set to 0x0002. Does that mean it will reset if a BOR occurs or has occurred? It appears to always be a value of 0x0002. Looking at the user guide a BOR occurs during the following events. 

    • Powering up the device
    • Low signal on RST/NMI pin when configured in the reset mode
    • Wake-up event from LPMx.5 (LPM3.5 or LPM4.5) modes
    • SVSH low condition, when enabled (see the PMM chapter for details)
    • Software BOR event

    I'm can rule out Powering up the device. 

    The RST/NMI seems to be tripped after waking up from LPMx.5, It doesn't appear to be the case as the reset doesn't happen everytime I put the board into LPM. However, my board does have the RST/NMI pin wired up to the JTAG 14 pin connector I have attached. I'll talk to the EE and see if a low signal there is causing the issue. 

    I'm not sure what SVSH is, I'll read up on that some more. 

    and I don't believe I'm doing a Software BOR at any point. But then again, I'm not sure how to do that, so I don't know if I am or not. More research here as well. 

    if you have a direction I should be researching first, that would be great. 

    Again thank you for your time. 

    Michael

  • It's still not clear to me (a) what you expect to happen vs (b) what actually happens.

    Which LPM are you using? LPM0-4 execute inline and wakeup executes the next instruction. LPM3.5/4.5 wake up via the reset vector. 

    If you're not sure whether there's a Reset involved, you can set a breakpoint at the second line of main (the debugger fools with the first line of main). Even better is a breakpoint at the Reset entry point (usually _c_int00), since at that moment much of the pre-Reset environment is preserved.

  • Bruce, 

    What I want to occur when I'm not interacting with the chip. is for it to go in and out of LPM on its own. The basic flow should look like this

    The main body of my software is a loop. So its setup to go in and out of LPM. I'm using LPM3. here is my setup LPM function

    void rtc_LP_Timer_setup(unsigned int lpt)
    {
    
        RTCCTL &= ~ RTCIE;
    
        do
        {
    
            CSCTL7 &= ~(XT1OFFG | DCOFFG);
            SFRIFG1 &= ~OFIFG;
        }
        while (SFRIFG1 & OFIFG);               // Test oscillator fault flag
    
        __enable_interrupt();
    
        flash(1,1000);
    
        RTCMOD = (lpt * 32) - 1;
        // Initialize RTC
        // Source = 32kHz crystal, divided by 1024
        RTCCTL = RTCSS_2 | RTCSR | RTCPS_7;
        RTCCTL &= ~RTCIE;
    }

    void enter_low_power_mode()
    {
    
        TB0CTL &= ~TBIE;
        TB0CTL &= ~MC_2;
        RTCCTL |= RTCSR | RTCIE | RTCSS_2;
        _bis_SR_register(LPM3_bits| GIE);
        RTCCTL &= ~RTCIE;
        RTCCTL &= ~RTCSS_2;
        TB0CTL |= TBIE | TBCLR | MC_2;
    }

    I have no doubt that the software is resetting itself. As you suggested, I threw a break point in at the second line and it trips. So its verified 

    Right now I have the LPM3 for 10 seconds before waking. It goes into LPM3 for 10 seconds, then wakes. It doesn't trigger a reset at that time. When the RTC generates an interrupt signal I use 

    _low_power_mode_off_on_exit();

    from within the ISR. 

    I also use 

    _low_power_mode_off_on_exit();

    when a usb device is connected. I have another ISR to recognize when a USB device is connected to exit LPM. 

    So I'm testing right now and it seems the system reset itself while I was in a delay loop. 

    I have to wait for 60 seconds between actions. So I wrote a delay function for milliseconds. the call

    delay_ms(60000);

    the function

    void delay_ms(unsigned int ms)
    {
    
        while(ms)
        {
    
            __delay_cycles(8000);
            ms--;
        }
    }

    I've read awhile ago that the delay_cycles() call shouldn't be used as it blocks interrupts, if I remember correctly. But I have plans on implementing a timer call, that will replace it at a later time. This was just easier for now. 

  • How is the Watchdog timer configured? User Guide (SLAU445I) Table 12-2 mentions a 16-second timeout (32kHz clock), which is between 10 and 60 seconds.

    __delay_cycles doesn't (in itself) block interrupts. If you use it in a context where interrupts are disabled, of course, they will be blocked for that long.

  • I believe I have disabled the watchdog timer, at the beginning of the program with

    WDTCTL = WDTPW | WDTHOLD;

    however, verifying that, the value of WDTCTL is 0x6980 or 110100110000000. The bit 7 is set to 1, so the watchdog timer is stopped. 

    I spent yesterday debugging, trying to figure out where exactly it resets. If there's a specific point in the program. I thought I narrowed it down to a 30 second delay_cycle, but then I commented out previous delays, and it occurred later, then I started to hook up a scope so I can check out the power supply power draw and see if there are any dips or spikes, and I noticed something funny when I was turning on and off the pump pin on the board. However, with doing nothing more than probing around, it started to work. I ran it for about an hour with no resets. I'm going to run it again today for several hours to see if there's a reset that occurs. See what happens. 

    I probably need to do a new question for this, but why is it that all the information I've found on delay_cycles being a bad practice, as they block interrupts? 

  • If you can breakpoint at the Reset entry, much of the pre-Reset context is preserved. (The name is something like _c_int00; in a pinch use the "Hard Reset" button in the Toolbar and see where it takes you.) The PC is gone, but the SP isn't. Walking back through the stack requires a fair amount of patience, but I have done it a number of times.

    I can't really comment on what you've read elsewhere. __delay_cycles doesn't (itself) disable interrupts. The usual argument is that "you should be using LPM", which is mostly true, though not always -- e.g. for very short delays it's cheaper than LPM. And it's simple, self-contained, and reliable.

    __delay_cycles isn't magic -- it generates a counting loop with the count scaled according to the instruction timings. You could do the same thing with a for() loop, but calibrating your loop (since the compiler can do all sorts of things to it) is quite difficult.

  • Bruce, 

    Where do I find _c_int00. I've done some searches and it references boot.h. Which I found in the src library of Code Composer, in my device directory. I attempted to add the file to my project exployer, but when I attempt to insert a break statement it tells me that the file is never called. 

    Am I looking at the correct file and/or how do i insert a breakstatement when _c_int00 is called?

    I attempt to insert the breakpoint at the STACK_INIT(); call

    void _c_int00_template(int NEEDS_ARGS, int NEEDS_INIT, int NEEDS_MPU)
    {
       STACK_INIT();
    
       if (NEEDS_MPU)
          __mpu_init();
       
       /*------------------------------------------------------------------------*/
       /* Allow for any application-specific low level initialization prior to   */
       /* initializing the C/C++ environment (global variable initialization,    */
       /* constructers).  If _system_pre_init() returns 0, then bypass C/C++     */
       /* initialization.  NOTE: BYPASSING THE CALL TO THE C/C++ INITIALIZATION  */
       /* ROUTINE MAY RESULT IN PROGRAM FAILURE.                                 */
       /*------------------------------------------------------------------------*/
       if(_system_pre_init() != 0)
       {
          if (NEEDS_INIT)
             _auto_init();
       }
    
       /*------------------------------------------------------------------------*/
       /* Handle any argc/argv arguments if supported by an MSP430 loader.       */
       /*------------------------------------------------------------------------*/
       if (NEEDS_ARGS)
          _args_main();
       else
          main(0);
    
       exit(1);
    }

    I've marked when I get these brownouts. Its completely random as far as I can see. I can get it when I plug in the USB device, I get it immediately after a BOR or it could be minutes after the device enters LPM3, when its meant to hibernate for 30 minutes. I can't see any discernible pattern. 

    UPDATED:  You know what never mind the above. I noticed the templete at the top of it. I found the correct call location. 

    CSTART_DECL _c_int00(void)
    {
       _c_int00_template(1, 1, 0);
    }

    I inserted a break statement right next to _c_init00_template(1,1,0); Now I'm just waiting for the brownout. 

     

  • Bruce, 

    As in my other reply I attempted to use your suggestion about _c_int00. I found the _c_int00 function located in boot.c. I inserted a breakpoint, however there was nothing in the SP. I figured I would check other files to see where the function was actually called and put the breakpoint at the call itself. I did a search of all records of the files in CCS and only found three files that had a reference to _c_int00. Boot.c, mpu_init.c, and pre_init.c. the mpu and pre file only have comments regarding _c_int00 no actually statements. 

    I also scanned the workspace for any refences to _c_int00 and only found references to _c_int00_noargs_mpu in an .xml file. 

    Could you point me where you had success prior? 

    Thank you for your time and help. 

    Michael

  • When I'm not quite sure which _c_int00 variant is used (based on CCS Project settings, I think) I hit the "Hard Reset" button in the Toolbar and see where it takes me. The button is roughly in the middle, with the icon that kind of looks like an MCU chip .

  • So I paused the program and hit the hard reset. (only way I could use the reset was if the program was paused, not sure if thats normal). It takes me right to 

    CSTART_DECL _c_int00(void)
    {
       _c_int00_template(1, 1, 0);
    }

    Thats the same function I found the other day. However, there is nothing in the call stack that I can see. 

    Just to clarify as its possible I'm not looking in the right place. I pull up the Debug view and under the micro-controller name is where I have been looking at the call stack.  

  • Actually I was talking about sifting through the stack (starting at the SP value) with the Memory Browser. As I said, it requires a fair amount of patience; I only do it when nothing else seems to be finding anything.

    If you decide to try, I suggest first finding words that look like code addresses. The first of these will be the most recent caller function; the Disassembly window can help with looking up names. You should probably budget an hour or so.

    And if you decide not to try, no one will blame you.

  • yea, I see what your saying. Reading through the documentation some more last night I came across references to the SP which is read out of the Registers. 

    Whats a code address? 

    I don't believe I have anywhere near the experience necessary to hunt this down. There's just too many unknowns. I'll make a go at it, but I don't think I'm going to be able to figure this out. Not sure where to go from here. 

    Bruce, as usually you have been a great help. I appreciate all the information. I truly appreciate it. 

  • OK. I didn't mean to distract you, I just tossed that out as one possible tactic. (By "code address" I just meant a number between 0x8000 and 0xff80, which is (high probability) a pointer into your code.)

    What have your other experiments found?

    One trouble is that we're seeing through a very small window into your program. Another tactic is to start removing pieces of the code until the symptom stops. That will give you (and the rest of us) a place to focus on.

  • Bruce, 

    You absolutely did not distract me. You're giving me advice and I'm grateful. I need to learn how to read the memory browser and use it to debug at some point. I just don't think I have the knowledge to do that right now. 

    I've already started to work backwards attempting to find the point where it works. Its time consuming as a BOR can occur within minutes of me launching the program or up to 39 minutes. 39 min has been the longest I've been able to run the program without a BOR. 

    Well working with a co-worker, he thinks its a interrupt issue, we removed the switch statement from the ISR for TimerB and just inserted an if statement with a reset of the flag

    // Timer0_B3 Interrupt Vector (TBIV) handler
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMER0_B1_VECTOR
    __interrupt void TIMER0_B1_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER0_B1_VECTOR))) TIMER0_B1_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
    //    switch(__even_in_range(TB0IV,TB0IV_TBIFG))
    //    {
    ////        case TB0IV_NONE:
    ////            break;                               // No interrupt
    ////        case TB0IV_TBCCR1:
    ////            break;                               // CCR1 not used
    ////        case TB0IV_TBCCR2:
    ////            break;                               // CCR2 not used
    //        case TB0IV_TBIFG:
    //
    //            //P1OUT ^= BIT0;
    //            //iiiii++;
    
        if(TB0IV_TBIFG)
        {
            my_seconds=my_seconds+1;
            if(my_seconds==60){my_seconds =0; my_minutes++;}
            if(my_minutes==60){my_minutes =0; my_hours++;}
            if(my_hours==24){my_hours =0; my_days++;}
        }
    
        TB0CTL &= ~TBIFG;
    //            break;
    //        default:
    //            break;
    //    }
    }

    Vs what I have commented out. 

    He is thinking that since I'm using two timers, Timer B & RTC, there must be something in the way they are counting that is causing interrupts to clash and cause a BOR. He seems to think that an interrupt is going off more than the Timer B is set up to do, at one sec intervals, and because of that its causing issues that pop up randomly. 

    my Timer B set up

    void active_timer_setup()
    {
    
        // ACLK, counter length, count mode, Divider, clear TBR, enable interrupt
        // 32768, 0FFFh, Continuous, /8, clear Enable
        TB0CTL = TBSSEL_1 | CNTL_1 | MC_2 | ID_3 | TBCLR | TBIE;
    }
    
    

    What I'm doing currently, is running the program that was handed off to me. Its only using a single timer, RTC,
    and I'm going to let that run for an hour or so. See if it was there originally or not. Then, I'm going to start working
    backwards from what I've done. Testing as I pull out modules of the code. Besides the addition of a second timer,
    my version of the code works with more external hardware, such as manipulating a pump and some solenoids.
    Organized the code a bit more, removing redundant statements by creating functions, new classes to organize them, etc.
    Lets just say there has been a lot of changes since the hand off code.

  • Hey Bruce, 

    So I commented out the entirety of the main body of my program. It now goes through the configuration and hits a while statement that does nothing. I let that run and it still had a BOR. So, I commented out the RTC timer yesterday and let it run with just TimerB

    active_timer_setup();
    void active_timer_setup()
    {
    
        // ACLK, counter length, count mode, Divider, clear TBR, enable interrupt
        // 32768, 0FFFh, Continuous, /8, clear Enable
        TB0CTL = TBSSEL_1 | CNTL_1 | MC_2 | ID_3 | TBCLR | TBIE;
    }
    // Timer0_B3 Interrupt Vector (TBIV) handler
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMER0_B1_VECTOR
    __interrupt void TIMER0_B1_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER0_B1_VECTOR))) TIMER0_B1_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
    
        switch(__even_in_range(TB0IV,TB0IV_TBIFG))
        {
            case TB0IV_NONE:
                break;                               // No interrupt
            case TB0IV_TBCCR1:
                break;                               // CCR1 not used
            case TB0IV_TBCCR2:
                break;                               // CCR2 not used
            case TB0IV_TBIFG:
    
                my_seconds=my_seconds+1;
                if(my_seconds==60){my_seconds =0; my_minutes++;}
                if(my_minutes==60){my_minutes =0; my_hours++;}
                if(my_hours==24){my_hours =0; my_days++;}
    
                break;
            default:
                break;
        }
    }

    No issues, I came back in and it had been running for 16 hours, no BOR. 

    So with that said I commented out TimerB and removed the comments for the RTC timer

     

    lpm_period = 30; //Seconds
    rtc_LP_Timer_setup(lpm_period);
    void rtc_LP_Timer_setup(unsigned int lpt)
    {
    
        RTCCTL &= ~ RTCIE;
    
        do
        {
    
            CSCTL7 &= ~(XT1OFFG | DCOFFG);
            SFRIFG1 &= ~OFIFG;
        }
        while (SFRIFG1 & OFIFG);               // Test oscillator fault flag
    
        __enable_interrupt();
    
        flash(1,1000);
    
        RTCMOD = (lpt * 32) - 1;
        // Initialize RTC
        // Source = 32kHz crystal, divided by 1024
        RTCCTL = RTCSS_2 | RTCSR | RTCPS_7;
        RTCCTL &= ~RTCIE;
    }
    ///////////////////////Timer interrupt service routine###############################################
    //
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=RTC_VECTOR
    //This is the interrupt code used
    __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_RTCIF))
        {
        case RTCIV_NONE:
            break;          // No interrupt
        case RTCIV_RTCIF:                  // RTC Overflow
        {
    
            // If time since last active is not greater than sleep time do not wake up fully.
            _low_power_mode_off_on_exit(); //Exit Low Power Mode 3
            break;
        }
    
        default:
            break;
        }
        //_bic_SR_register_on_exit(LPM3_bits); // Exit Low Power Mode 3
    
    }

    And within an hour and half it reset. I understand that this doesn't necessarily mean that RTC is the problem. But this is the best lead thus far. 

    What I find interesting is in rtc_LP_Timer_setup() I have disabled the interrupt. I inserted a break point in the RTC ISR and its never tripped.

    What would cause a BOR related to the BOR? I know a BOR occurs if I'm exiting LPM3.5, but I'm never entering LPM3.5. I never make the call

    _bis_SR_register(LPM3_bits| GIE);

    as its been commented out in the main loop. And previously when I entered LPM it was LPM3, as while in LPM OSCOFF was still enabled. 

    any thoughts?

  • Is the RTC setup function called more than once?

    Also, what does flash() do?

    [Edit: I forgot to ask: You mentioned pumps and solenoids. Are they pretty far away (physically and electrically)?]

  • Is the RTC setup function called more than once?

    • Yes and no. With the program fully implemented the RTC setup is called in the beginning to set the default LPM time. However, there is a cmd the user can call that will update the LPM if they need a shorter or longer time. The command calculates the time they need then calls RTC setup to apply the new time. 
    • However, in the programs current form, where I have the majority of the code commented out. it only calls RTC setup that one time. With that one call it still trips a BOR

    Also, what does flash() do?

    • Flash is a delay, that was part of the original software that was handed over to me. Its original purpose was to flash the LEDs on the development board. Now it just calls a delay for what ever time you place on it. I took it out, as Its not necessary and it still has a BOR.  

    [Edit: I forgot to ask: You mentioned pumps and solenoids. Are they pretty far away (physically and electrically)?]

    • No I wouldn't consider them to be at a distance.  I would say there's maybe a foot of wire that's coming off the board currently that runs to the pump or sensor. The solenoids aren't actually hooked up to the board at the moment.

    So currently I am configuring a new program. Slowly pulling things in from the original and see if I see the same issues. 

  • Hey Michael,

    Just trying to catch up on this long thread here.  Sorry if I miss something.  

    First, A BOR is a device reset, and can only be caused by a few events.  All of which are listed in section 1.2 of the Family User's guide.  http://www.ti.com/lit/ug/slau445i/slau445i.pdf     They are pretty much all waking from LPMx.5 or an external voltage dig on VCC or RESET.  

    If you are seeing a BOR, then it's probably a hardware issue.  Are you seeing any noise or dips on VCC or RESET? 

    If it's software related, then it's probably not a BOR.  The SYSRSTIV register actually nests reset sources. (Section 1.3.7)  If you've never read the register, then it will probably always return BOR from the initial power-up as it's the highest priority interrupt. 

    For now, I would read the register in a loop with a break point at your software's startup until it reads 0x00, watching each value.  I imagine that you will see something besides a BOR that will lead us in the right direction.

    Thanks,

    JD    

  • JD, 

    Hello, Thanks for jumping in with support. This community has been a great resource. 

    No noise or dips on vcc or RESET. Those were the first two areas of the board we looked at. Keep in mind, when I run the original code or any of the sample code from TI, it runs just fine. Never resets, unless its meant to. So I think its fairly safe to say its not a hardware issue. That and I've tested my code that fails on the development board as well. It still fails on that. 

    With that being said, I believe I may have stumbled across the issue last night. So I created a new project and I started fresh with the original software. I started pulling over all the changes I've made module by module. I would run each section for an hour or until it reset. Well the section where I initialize the GPIO ports caused a reset. 

    Lets go back to what I did. So as I was writing the software I came to a point where I stopped adding new functionality and started to go back and clean up the code. Adding comments mainly, but I also took some time to look at the warnings and advice sections related to power consumption. So one of the things the advice gave was that ports 7 - 10 and A - E were not initialized and that they should be initialized to defaults. Well, looking at the chip layout, I didn't see any port 7 - 10 or A - E, so I figured they weren't there, whats the harm in just initializing them. So in my GPIO initialization function I did this. 

    void init_GPIO()
    {
    
        P1DIR = 0x00; P2DIR = 0x00; P3DIR = 0x00; P4DIR = 0x00; P5DIR = 0x00; P6DIR = 0x00;
        P1REN = 0xFF; P2REN = 0xFF; P3REN = 0xFF; P4REN = 0xFF; P5REN = 0xFF; P6REN = 0xFF;
        P1OUT = 0x00; P2OUT = 0x00; P3OUT = 0x00; P4OUT = 0x00; P5OUT = 0x00; P6OUT = 0x00;
        P1SEL0 = 0x00; P2SEL0 = 0x00; P3SEL0 = 0x00; P4SEL0 = 0x00; P5SEL0 = 0x00; P6SEL0 = 0x00;
        P1SEL1 = 0x00; P2SEL1 = 0x00; P3SEL1 = 0x00; P4SEL1 = 0x00; P5SEL1 = 0x00; P6SEL1 = 0x00;
        P1IES = 0x00; P2IES = 0x00; P3IES = 0x00; P4IES = 0x00; P5IES = 0x00; P6IES = 0x00;
        P1IE = 0x00; P2IE = 0x00; P3IE = 0x00; P4IE = 0x00; P5IE = 0x00; P6IE = 0x00;
    
        P7DIR = 0x00; P8DIR = 0x00; P9DIR = 0x00; P10DIR = 0x00;
        P7REN = 0xFF; P8REN = 0xFF; P9REN = 0xFF; P10REN = 0xFF;
        P7OUT = 0x00; P8OUT = 0x00; P9OUT = 0x00; P10OUT = 0x00;
        P7SEL0 = 0x00; P8SEL0 = 0x00; P9SEL0 = 0x00; P10SEL0 = 0x00;
        P7SEL1 = 0x00; P8SEL1 = 0x00; P9SEL1 = 0x00; P10SEL1 = 0x00;
        P7IES = 0x00; P8IES = 0x00; P9IES = 0x00; P10IES = 0x00;
        P7IE = 0x00; P8IE = 0x00; P9IE = 0x00; P10IE = 0x00;
    
        PADIR = 0x00; PBDIR = 0x00; PCDIR = 0x00; PDDIR = 0x00; PEDIR = 0x00;
        PAREN = 0xFF; PBREN = 0xFF; PCREN = 0xFF; PDREN = 0xFF; PEREN = 0xFF;
        PAOUT = 0x00; PBOUT = 0x00; PCOUT = 0x00; PDOUT = 0x00; PEOUT = 0x00;
        PASEL0 = 0x00; PBSEL0 = 0x00; PCSEL0 = 0x00; PDSEL0 = 0x00; PESEL0 = 0x00;
        PASEL1 = 0x00; PBSEL1 = 0x00; PCSEL1 = 0x00; PDSEL1 = 0x00; PESEL1 = 0x00;
        PAIES = 0x00; PBIES = 0x00; PCIES = 0x00; PDIES = 0x00; PEIES = 0x00;
        PAIE = 0x00; PBIE = 0x00; PCIE = 0x00; PDIE = 0x00; PEIE = 0x00;
    
        // Disable the GPIO power-on default high-impedance mode
        // to activate previously configured port settings
        PM5CTL0 &= ~LOCKLPM5;
        ////////////////////////Set up all ports/////////////////////////
    }

    This function is only called once at the beginning, just to default all pins. Just to prevent anything from floating.

    Well it seems that I shouldn't have done that for 7-10 either/or A-E. As I've commented out those lines and the software has now been running with no resets for almost 17 hours. 

    Digging into the lettered ports, it seems these are paired ports. So Port A is a combination of Port 1&2. As I said before ports 7 -10 aren't on this chip. As Port A-E are actual register's, I'm assuming the real fault lays with initialization of ports 7-10. There doesn't seem to be any reference to the letter ports in either of the data sheet or manual. I did do a search on it, in the forums to find the information on it. 

    I'm going to continue to let this run for the day and see what happens, but its always reset within an hour before, so this is a wildly good sign. 

  • Thanks for posting this, it's useful. I was just scratching my head over this a few weeks ago: (a different) MCU had a bunch of _MSP430_HAS_PORTn_R_ which I was pretty sure didn't exist. Setting the registers (in my case) had no evident bad effects, but now I know to stay away just in case.

  • Yea not so fast. It has restarted. 

    ...................................

    Yea that's ^ me crying. 

    So its weird. as I've never been able to get this to run for this long before without resetting. But I ran it over night and 17 hours go by no issue. So why did it run for so long? was it the port settings for 7-10, A-E? maybe was a factor, but not so sure anymore. 

  • JD, 

    So I went back to look at SYSRSTIV and it was no longer showing, don't remember what it was. So I changed the first few lines of code. Looks like this now. 

    int main(void)
    {
    
        /////////////////////////////Setting up services etc/////////////////
        start_read = 0;
        readFlag = 0;
        SYSRSTIV = 0x00;
    
        ...
        ...
        ...
    }

    I wrote to SYSRSTIV as documentation states this will reset all pending flags. I do not think I'm doing this correct, as when it resets and hits the block at readFlag=0;

    its showing there have been no flags, SYSRSTIV = 00000000000000000 - NONE  

    I'm not sure what you mean by doing a loop and reading the register. Doesn't the block and looking at the registers tab do the same thing?

    is there any chance one of these two warnings are playing a role?

    Description Resource Path Location Type
    This project was created using a version of compiler that is not currently installed - 18.1.4.LTS [MSP430]. Another version of the compiler will be used during build - 18.12.2.LTS. See 'Help > Install New Software' and select 'Code Generation Tools Updates' to check if this compiler is available through a CCS update. Visit <a href="liveaction:OpenAppCenter">CCS App Center</a> to get the latest compiler support. Or <a href="http://software-dl.ti.com/codegen/non-esd/downloads">download</a> and install the compiler, then register it with CCS through 'Preferences > CCS > Build > Compilers'. flow_Recording properties Problem
    Description	Resource	Path	Location	Type
    #10229-D null: output section ".data" refers to load symbol "_nop" and hence cannot be compressed; compression "lzss" is ignored	flow_Recording		 	C/C++ Problem
    
    Description	Resource	Path	Location	Type
    #177-D subscript out of range	main.c	/flow_Recording	line 313	C/C++ Problem
    

  • What JD was saying is that there may be more than one "reset reason". If you read the IV, you get one and then the next one appears. (Eventually it goes to 0.)

    For most/all of the registers that change if you read them, the debugger has a special access method that can read the value without "reading", so the value stays put. If the program doesn't read the IV, you won't see any that are "hidden" behind the first. Writing a 0 clears them all, so you don't see any of them. Seeing IV==0 before you write the 0 looks odd. (I personally would spot check the assembly code and make sure the instructions didn't get re-ordered. A Wise Guy once said "'Should' is the weakest force in the Universe.")

    1) The compiler version almost never makes a difference. You can fix this on the Build Settings->General page ("Automatic" or some such).

    2) I'm not quite sure what would trigger the second one. It sounds harmless, but if you can make it disappear that's probably good. Do you recognize "_nop"?

    3) Looks quite suspicious. Is it true? What code is at main.c line 313?

  • Ok that has clarified some things. Makes sense now. 

    1) "Manage the project's target-configuration automatically" is already selected under Build Settings > General. 

    2) nope don't recognize _nop. mystery

    3) yea this has been fixed, Simple mistake

    So to add to our grand story. I left it to run over night again. Since 2:21pm yesterday. Roughly 16 hours again. HOWEVER, this time I disconnected the JTAG. Its still running strong. I'm going to keep letting it run. Using the android app I can pull data off the board to check the run time. So if it resets. the time would reset as well and I would know roughly how long ago it last reset, but not how many times. I just pulled the data from the board and its running strong at 16+ hours. so yea. 

    I decided to pull the JTAG cable as one of the lines is connected to the RST/NMI pin and I wanted to see what would happen. 

    What are your thoughts on this? Here is the schematic for that section if that helps. 

    I'm also thinking it might be time to just scrap this and go in a new direction. We need better power savings anyway. So I might pull the infinite loop and implement LPM3.5, so a reset occurs anyway. Of course not knowing the cause is bad form, and really needs to be addressed. Not sure where to go from here. 

  • I guess there isn't an "Automatic" for "Build Settings->General->Compiler". Just choose the compiler version the Warning mentions, I suppose. I'm pretty sure it isn't important, but that Warning (when I get it) is kind of annoying.

    What was at the other end of the JTAG wires? I don't use 4-wire JTAG unless I have to -- I wouldn't know how to interpret Boundary Scan output anyway.

  • Well with the JTAG disconnected, the software just running, I'm now at 1 day 17 hours 23 min of run time. Looking good. 

    There has to be something related to the JTAG connection that is happening, while connected to the PC that is causing resets. It doesn't appear to cause any resets if the PC is hibernating overnight as I've seen it run through the night with no resets, but within 30 min of the PC coming out of hibernation it will reset. 

  • Hey Michael,

    Catching back up and wanted to check on the progress here.  Any more unexpected resets?  

    I'm not sure why the JTAG would cause a reset in this case.  It could be as simple as the additional wire/cable is picking up noise on the RST line or it could be something more complex.  When the JTAG/Debugger is running, it's actively engaged with the core and can change small behaviours and especially timings.  I'm not sure how these things could cause a reset, but I guess it's possible.  

    Feel free to respond back here if you are still having issues.  

    Thanks,

    JD

  • Hey JD, 

    AT this point I think we are chalking it up to a JTAG issue while the PC is running. It has been running for roughly 6 days straight with no issues, with the JTAG disconnected. I connected the tablet daily to pull sensor readings and time information to verify things are going well. Some more redundancies need to be implemented, but I think we feel this is in a good place. 

  • Thanks for the update, Michael.  Good to hear!  

**Attention** This is a public forum