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.

MSP430FR2311: Strange/Undocumented behavior when disabling/enabling individual timer interrupts (TB1CCTL0.CCIE)

Part Number: MSP430FR2311
Other Parts Discussed in Thread: MSP430FR5994

Hello all, especially , , , and Chester Gillon,

I'm also disabling/enabling the CCIE and seem to be running into the same issue where the part (MSP430FR2311 in my case) is jumping to an invalid PC (0x020010 currently, but has varied as I've changed code) after a very short period of time.  I also suspect it is related to disabling/enabling the CCIE while the timer is running, which was my conclusion before finding your thread (https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/895839/msp430fr5994-strange-undocumented-behavior-when-disabling-enabling-individual-timer-interrupts).  You seem to have thoroughly debugged the issue as much as you can (more than I could!) but there was no conclusion/resolution to the issue, especially an official TI response.  I don't see an errata for this issue on the original MSP430FR5994, so is there a recommended workaround?  I also observed that adding a NOP after the CCIE = 0 seems to resolve the issue, but since adding or removing a line of C code in one place or another also seems to resolve the issue (for a while, until it pops back up unexpectedly) I want something that is guaranteed to work.  I have also created a simple test project to demonstrate the issue (runs on the MSP430FR2311 Launchpad), but I don't think it is relevant at this time since the other thread had very good documentation, including sample code with better troubleshooting features.

Any help would be appreciated!  Thanks!

TJ

  • Hello TJ,

    I'm also waiting for official statement for some time now Slight smile

    However, I've run code with "NOP" for a long time and I don't have any problems.

    cheers,

    Filip

  • Thanks for the quick reply!  It would be great if we could get an official response from TI after 2 years to close out the thread, but if you've been using the NOP solution for 2 years, that seems to be pretty robust.

    Just to confirm, are you doing something like the following?  Just a NOP after disabling the capture/compare interrupt (CCIE)?  Or are you also adding a NOP after re-enabling?  Are you adding the NOP after any other peripheral interrupt disables, just in case?

    //disable the TB1 CCR0 capture/compare interrupt
    TB1CCTL0 &= ~CCIE;
    
    //NOP to prevent micro from corrupting PC
    _NOP();
    
    //perform atomic operation on variable(s) modified by TB1 CCR0 ISR
    
    //re-enable the TB1 CCR0 capture/compare interrupt
    TB1CCTL0 |= CCIE;

  • By memory, I think if you disable peripheral int, you always should put NOP instruction anyway.
    When enabling, there is no need.
    I'm using these macros :

    #define __EVALUATE_STR__(X) #X
    #define __EVALUATE_STR2__(X) __EVALUATE_STR__(X)
    //#define CLR_BIT_ATOMIC_B(reg, bitn) asm("	BIC.B #" __EVALUATE_STR2__(bitn) ", &" #reg "\r\n	.global " #reg)
    //#define CLR_BIT_ATOMIC_W(reg, bitn) asm("	BIC.W #" __EVALUATE_STR2__(bitn) ", &" #reg "\r\n	.global " #reg)
    
    // Use these to disable peripheral interrupts, since NOP is MANDATORY after each peripheral int disable (not documented MSP "feature") :
    // https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/895839
    #define CLR_BIT_ATOMIC_B(reg, bitn) asm("   BIC.B #" __EVALUATE_STR2__(bitn) ", &" #reg "\r\n   NOP\r\n   .global " #reg) 
    #define CLR_BIT_ATOMIC_W(reg, bitn) asm("   BIC.W #" __EVALUATE_STR2__(bitn) ", &" #reg "\r\n   NOP\r\n   .global " #reg)
    
    #define SET_BIT_ATOMIC_B(reg, bitn) asm("	BIS.B #" __EVALUATE_STR2__(bitn) ", &" #reg "\r\n	.global " #reg)
    #define SET_BIT_ATOMIC_W(reg, bitn) asm("	BIS.W #" __EVALUATE_STR2__(bitn) ", &" #reg "\r\n	.global " #reg)
    

    But if this is too much, just insert __no_operation() compiler intrinsic after disabling INTs, including timer CCR ones. Whatever works for you.

    Compiler should not optimize ASM or intrinsic code in any level of optimizations.

    Regards,
    Filip

  • Thanks!  I'll wait a day or two to see if we get some sort of official TI response.  If not, I'll mark your reply as the solution.

  • Hi TJ,

    Any update here, do you still need support?

    Thanks!

    Best Regards

    Johnson

  • Hi Johnson,

    We seem to have a workaround, but it would good if TI could confirm the root cause of the program counter (PC) corruption (see original thread for a lot of troubleshooting and suspected root cause).  TI should also state whether adding a NOP after disabling peripheral interrupts is a guaranteed solution (only you have the ability to check the Verilog).  An open question is whether this issue only applies to this specific peripheral interrupt (timer A/B CCIE) or all peripheral interrupts (other timer interrupts, ADC, RTC, eUSCI, etc.).  Another open question is which parts are affected (may not be important if the universal solution is to add a NOP after disabling peripheral interrupts).  I also think that if a NOP is required, this should be listed as an errata on all affected parts, or the datasheets should be updated to state this requirement.  It would be even better if the compiler would add the NOP, but I don't know if that is feasible.

    Had this issue been resolved 2 years ago, it would have saved me at least a week's worth of troubleshooting and frustration (I do read the datasheet and errata!).

    Thanks!

  • Hi TC, 

    Thanks for your feedback, I will try to analysis the issue. I will update if any process.

    Thanks!

    Best Regards

    Johnson

**Attention** This is a public forum