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.

MSP430FR5969: Forgets program or program is corrupted

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

I'm having a similar issue to this one here.

My code is executing fine. Sometimes for 1 day, sometimes for 3 months. Then, it just stops working. Cycle power and it is like the device is dead or it has forgotten it's program. 

If I reprogram the device, it starts working again. I have seen this issue on multiple devices so I do not think it is just a bad chip.

Clearly something is getting corrupted. I looked through the errata, but I can't see how any of the errata apply to what I am doing.

Any suggestions on where to look? Has anyone else solved this issue?

I also found this thread, but that issue was handled outside of e2e.

  • This feels like an MPU issue. This is an MSP430FR, so it is very easy for your firmware to overwrite itself. For example, a buffer overrun could easily overwrite your firmware. If not done so yet, read about the MPU and how to protect your code. See this document: http://www.ti.com/lit/an/slaa628/slaa628.pdf

  • Hey Salvatorre,

    I agree with Mike that this is most likely a software error of some time that could be overwriting some critical section of FRAM.  You could try dumping the memory from the corrupted devices and compare to a good image, but I would recommend implementing the MPU and looking for buffer overruns and invalid pointer accesses, etc. 

    The document he linked should be very useful.  

    Thanks,

    JD 

  • Thank you guys, very much! I will read up on the MPU and report back what I find.

  • I read over SLAA628 - FRAM Best Practices. Wow, this was very helpful. I was not using MPU. It's crazy to think that I have done so much with FRAM MSP430's and didn't even know about MPU.

    That said, I'd like to help out anyone who may be interested.

    However, I am running at 8 MHz in active mode:

    void initClk()
    {
        CSCTL0_H = 0xA5;
        CSCTL0_L = 0;
        CSCTL1 = DCORSEL + DCOFSEL1 + DCOFSEL0;     /* Set DCO setting = 8MHz*/
        CSCTL2 = SELA_1 + SELS_3 + SELM_3;          /*set ACLK - VLO, the rest = MCLK = DCO*/
        CSCTL3 = DIVA__16 + DIVS_0 + DIVM_0;		/* set clock dividers to 0. Set ACLK/16*/
    
        /* Globally enable interrupts */
        __bis_SR_register(GIE);
    }

    2. Memory Layout Partitioning. I'm well familiar with command files from my work with C2000 chips, and I had a very old cmd file: Version 1.127. When I changed my device in properties and had CCS create a new cmd file, it produced Version 1.207. I didn't realize that I likely need that right away so before that, I moved on with the FRAM Best Practices doc.

    3. I compared my cmd file using DiffMerge to C:\ti\CC3100SDK_1.2.0\cc3100-sdk\platform\msp430fr5969lp\example_project_ccs\getting_started_with_wlan_station\lnk_msp430fr5969.cmd and the only difference was that I had added two lines between .stack and .infoA:

    	.TI.noinit 		: {} > FRAM 			/* For #pragma NOINIT */
    	.TI.persistent 	: {} > FRAM 			/* For #pragma PERSISTENT */

    I recall that I got these lines from some e2e post to solve a problem I was having with variables being reset on power cycle. That was a long time ago.

    IS IT POOR PRACTICE TO PUT A POINTER TO A FUNCTION IN PERSISTENT? I have this warning as a result: #10229-D null: output section ".data" refers to load symbol "initFunction" and hence cannot be compressed; compression "lzss" is ignored

    I enabled MPU using the MPU Wizard and I got these errors:

    undefined first referenced
    symbol in file
    --------- ----------------
    MPUSEG C:\ti\ccs910\ccs\tools\compiler\ti-cgt-msp430_18.12.2.LTS\lib\rts430x_lc_rd_eabi.lib<mpu_init.c.obj>
    __mpusam C:\ti\ccs910\ccs\tools\compiler\ti-cgt-msp430_18.12.2.LTS\lib\rts430x_lc_rd_eabi.lib<mpu_init.c.obj>
    __mpuseg C:\ti\ccs910\ccs\tools\compiler\ti-cgt-msp430_18.12.2.LTS\lib\rts430x_lc_rd_eabi.lib<mpu_init.c.obj>

    I solved that by Project >> Add Files: C:\ti\ccs910\ccs\ccs_base\msp430\lib\FR59xx\MSPMPU_INIT_LIB_CCS_msp430_large_code_restricted_data.lib
    aka
    ${CCS_BASE_ROOT}\msp430\lib\FR59xx\MSPMPU_INIT_LIB_CCS_msp430_large_code_restricted_data.lib

    When I ran my code I couldn't write to my PERSISTENT memory anymore.

    I found that my linker file didn't have persistent in the right spot when I compared it to a freshly generated cmd file. So, I started using the freshly CCS generated cmd file. The new file has this:

    SECTIONS
    {
        GROUP(RW_IPE)
        {
            GROUP(READ_WRITE_MEMORY)
            {
               .TI.persistent : {}              /* For #pragma persistent            */
               .cio           : {}              /* C I/O Buffer                      */
               .sysmem        : {}              /* Dynamic memory allocation area    */
            } PALIGN(0x0400), RUN_START(fram_rw_start)

    So then I got errors that the program wouldn't fit in memory for .data and .stack. However, my old cmd file had .data and .stack in RAM just like the new file, but I had .bss in FRAM and not RAM.

    But, when I changed .bss to FRAM, the program just wouldn't work. What I learned was that now that I am using the MPU I just can't assign sections of code to FRAM because it is protected by the MPU. I had a few global string variables that were just too long. They had to be put in FRAM so I #pragma PERSISTENT(...) those variables and voila, my code worked again.

    Now, I have to cross my fingers that I can figure out what part of the code was causing the FRAM write to program memory. 

    IS THERE ANY OTHER CODE I NEED SO THAT I WILL GET A PUC IF THIS ERROR OCCURS?

    For instance, is it recommended to now have some of this code that I found in msp430fr59xx_mpu_02.c or did the MPU Wizard handle this?

      WDTCTL = WDTPW | WDTHOLD;                 // Stop WDT
    
      // Configure GPIO
      P1DIR |= BIT0;                            // Configure P1.0 for LED
    
      // Disable the GPIO power-on default high-impedance mode to activate
      // previously configured port settings
      PM5CTL0 &= ~LOCKLPM5;
    
      while (MPUCTL1 & MPUSEG2IFG)              // has reset occurred due to Seg2
      {
        P1OUT ^= BIT0;                          // Toggle LED
        __delay_cycles(30000);                  // Delay to see toggle
      }
    
      // Configure MPU
      MPUCTL0 = MPUPW;                          // Write PWD to access MPU registers
      MPUSEGB1 = 0x0600;                        // B1 = 0x6000; B2 = 0x8000
      MPUSEGB2 = 0x0800;                        // Borders are assigned to segments
      
      //  Segment 1 - Execute, Read
      //  Segment 2 - Violation, Execute, Read
      //  Segment 3 - Execute, Read
      MPUSAM =             MPUSEG1RE | MPUSEG1XE |
               MPUSEG2VS | MPUSEG2RE | MPUSEG2XE |
                           MPUSEG3RE | MPUSEG3XE |
                           MPUSEGIRE | MPUSEGIXE | MPUSEGIWE;
      MPUCTL0 = MPUPW | MPUENA;               // Enable MPU protection
    
      Data = 0x88;
    
      // Cause an MPU violation by writing to segment 2
      ptr = (unsigned int  *)0x6002;
      *ptr = Data;
    
      while(1);                                 // Code never gets here

    OTHER NOTES:

    There appears to be a typo in section 6.3.1:
    sytem_pre_init.c should be system_pre_init.c?

  • Hey Salvator,

    Glad to hear that the document is useful and for identifying the typo in section 6.3.1.  There is a document feedback link on the bottom of the page of all our documents for reporting any possible small errors in the future.   Don't worry about this one, I already submitted it to the team.    

    I think this is a useful summary for those who might be working with MPU for the first time.  

    As for the code to check for MPU access errors, I would say that this would be a good best practice.  Putting this check-in will at least let you know that the error happened and give you a root cause if your application ever seems to "randomly reset"

    Thanks,

    JD

**Attention** This is a public forum