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.

MSP430FR2111: After programming, the comparator sometimes fails (~50% chance of failure).

Part Number: MSP430FR2111
Other Parts Discussed in Thread: MSP-GANG, MSP-FET, MSP-TS430PW20

I have completed three different low volume builds.  Each build added more and more protection circuitry along with more care in assembly and handling.  Yet, each build gives a yield of about 50% failure.  The failure is determined by checking the voltage on pin 10, which is internally connected to the output of the comparator (eCOMP), after programming.

 I have done ESD testing on a couple of working boards and they are able to withstand 8 kV direct contact without damage.  Before programming all voltage levels are in an acceptable range on all boards.  Before programming, pin 10 measures ~1.1V.  After programming, a board fails if pin 10 measures 3.3V.  On a good board pin 10 measures 0.0V.  According to theory, the output of the comparator (pin 10) should not be a logic high, because zero volts is applied (measured at the pin) to the positive input of the comparator and the negative input of the comparator is connected to a DAC whose output is set to 0.75 * Vcc (2.475V).   If the code was wrong or eCOMP misconfigured, then no boards would work.

If the MSP430FR2111 is replaced, there is a chance that the board will start working.   When the MSP430 is replaced and the board starts working, this makes me believe that the problem is not due to external circuitry on the board or faulty programming.  I am not sure what the next step should be in troubleshooting this problem.

  • Hi David,

    On the failed boards, can you perform a continuity test with a multimeter to make sure that the pin isn't being shorted to another part of the board that can drive the pin high?

    Is the part kept within the allowed temperature and moisture level range outlined in JEDEC J-STD-020  when the part is being soldered onto the board as described in the Absolute Maximum Ratings section of the MSP430FR2111 Datasheet?

    Regards,

    Ryan

  • Hi Ryan,

     

    I have verified that the input pin to the comparator is correctly connected and that it is not shorted to any other signal.  This has been done to the current build and the previous builds. 

     

    Attached is a schematic for your review.  Also, this same problem was reported on a previous trouble case 1-3452112541.  I closed that case believing that the issue was due to ESD or assembly issue. 

    Since then, I took extra care in handling and assembling the boards.

     

    After adding ESD diodes and successfully testing the boards with an ESD gun to 8 kV direct contact, I found the boards to be robust with regards to ESD.  Of course, ESD protective measures were used in assembling the boards.

     

    On the 2nd and 3rd builds I was very careful about keeping the MSP430 in a sealed moisture proof bag and the humidity indicator card showed blue (okay) at the 5% level.  The ICs were always stored at room temperature. 

     

    As far as the solder profile goes, I used a low-temperature lead-free solder.  The peak temperature for this solder is 165 degrees C. 

     

    I hope that you will agree that I have done all that I could to account for all of the requirements to assemble these boards.

     

    Regards,

    David Harding

    171321.PDF

  • Hi David,

    It sounds like you've taken a lot of care in board assembly and ESD protection! I'm working on contacting the people who worked on your previous case to make sure we're on the same page.

    Based on your schematic, it looks like you're programming your devices using Spy-Bi-Wire. Is that correct? What tools are you using to program the devices and have you had any issues in verifying the program on the devices during connection? Is it possible you can try isolating the FR2111 RST line from U6 on your schematic during programming and replace R13 with a 47k resistor?

    Regards,
    Ryan
  • Yes, I am using Spy-Bi-Wire to do the programming. I have used three devices to program the boards over the course of this project. My first build was programmed with the MSP-FET430UIF. Later I used the MSP-FET emulation tool to program the boards. The last two builds were programmed with the MSP-Gang programmer. Concerning isolating the reset, the previous designed used the recommended RC combination, but those designs also had this same problem.
  • Hi David,

    It looks like in the email thread with the previous case, you said that the comparator output goes low if the code is reset. Does the comparator begin responding to the FPS at that point or is the comparator output then stuck low?

    Do you happen to have an MSP-TS430PW20 target board you can test one of the trouble MCUs with? First try powering the board without loading a program on the MCU again and see if P2.0 responds to an input on P1.0. Then if possible try connecting to it to reload the comparator test program you sent in the previous case email thread.

    Regards,
    Ryan

  • Once the comparator fails it does not recover. 

    I do have a MSP-TS430PW20 evaluation board.  I have modified one of my boards by removing the MSP430 and running wires from the footprint of the MSP430 to the headers on the MSP-TS430PW20.  This will allow me to test multiple MSP430FR2111 devices without concerns for different environments due to assemble. 

    This also allows me to test different sequences of connecting the AC power, debugger/programmer, serial port, etc.  I am recording the connection sequence and the DC voltage of each pin during bring up.  I will let you know the result once I have compiled the data.

  • Hi Ryan,

    During my testing, I found that pin 11 (P1.7) measured 3.8 V while the chip is programming (i.e. before the DIO is initialized).  This is because of the base of Q2 (see schematic) is pulled up to 5V while the DIO is in high impedance state (prior to DIO initialization). 

    Clearly this condition needs to be fixed.  However, I would like to know if Texas Instruments believes this condition is likely to be the root cause of my problem.

    I have tested ten MSP430FR2111 on the MSP-TS430PW20 evaluation board that was wired to all of the signals on my board. Three of the ten IC failed.  Would this over-voltage condition cause this kind of random failures?

  • Hi David,

    It is difficult to say if that would be the root cause for the comparator behavior. The datasheet says the absolute maximum rating for a voltage applied to any pin is Vcc + 0.3 with an upper value of 4.1 V. Can you test programming multiple ICs through the MSP-TS430PW20 with all connections to your board except for P1.7 to see if more devices fail? Did the comparators on the devices function correctly before being programmed with the connections to your board?

    Thanks,
    Ryan

  • I just received 50 chips for testing. Below are the results for the first few that I have tested.

    I ran the test where all the signals from my board were connected, except P1.7 (the signal that measured 3.8 V). The first two chips passed, the third chip failed. 

    Next I removed all of the signals coming from my board except Vcc, ground, SBWTCK, and SBWTDIO. The first chip that I programmed and tested failed.

    Next I removed all signals from the MSP-TS430PW20 and reset all of the jumpers so that the evaluation was reconfigured as it came from the factory. I then programmed a device.  After programming, I connected the FPS signal and ground from my board to check the output of the comparator.  The first chip I tested failed.  I preformed the same test on another chip and it passed.

    So, as it stands right now, some of the MSP430FR2111 device fail after being programmed using the MSP-FET and the MSP-TS430PW20 evaluation board.

    I have attached a text file that contains my C code. Please review it to see if anything concerning is apparent.  Please remember that typically there is no indication of the problem until the subroutine Init_eCOMP() is run.  I always believed that this was due to the init_eCOMP subroutine making the connection between the output of the comparator and the IO pin, but may be something else is going on.

      Do you have any further suggestions?

    PwrCtrlBrd_C_code.txt
    //******************************************************************************
    // Copyright (c) 2017 Invivo Corporation all rights reserved
    // Project: Power Control Board for the UroNav Connect project
    // Author: David Harding
    // Date: July 2017 - Initial code
    //******************************************************************************
    //  MSP430FR2111 PwrCtrlBrd - Initialize microcontroller, execute main loop
    //
    //  Description: The microcontroller monitors the front panel switch (FPS) for
    //  two events.  If the FPS is press for more than 200 ms and less than 6 s,
    //  then the microcontroller determines if it should power up or power down the
    //  main power supply (MPS); i.e. the UroNav system. If it needs to power down,
    //  it issues a serial command that request a shutdown event to the single board
    //  computer (SBC).  The SCB displays a dialog box to the user.  If the user
    //  cancels the shutdown, the state is unchanged (i.e. powered up).  If the
    //  user confirms the shutdown, the SCB is shutdown by the UroNav program.  The
    //  PwrCtrlBrd detects the 5 V supply on the SCB is down and completes the
    //  shutdown by turning the MPS off.
    //
    //  The SBC may also initiate a shutdown.  If the SBC completes its shutdown, the
    //  PwrCtrlBrd detects the 5 V supply on the SCB is down and then shutdowns down
    //  the MPS.
    //
    //  If the FPS is pressed for 6 s or more, then the microcontroller will disable
    //  the main power supply (MPS) without requesting a shutdown event from the SBC.
    //  **********************  Microcontroller configuration  *********************
    //  P1.0 - Set up as an input to the comparator Channel C0 (FPS sense)
    //  P1.1 - Set up as DIO input to sense +5V from SBC (generates interrupt on low-to-high)
    //  P1.2 - Set up as UART Rx
    //  P1.3 - Set up as UART Tx
    //  P1.4 - Set up as DIO output to drive UART DTR
    //  P1.5 - Set up as DIO input to sense UART DSR
    //  P1.6 - Set up as DIO output to drive low current on-board LED
    //  P1.7 - Set up as DIO output to drive the MPS inhibit signal
    //  P2.0 - Set up as DIO output to test point (comparator output - Cout)
    //  P2.1 - Set up as DIO output to drive LED on FPS
    //  P2.6 - Set up as DIO output (unconnected)
    //  P2.7 - Set up as DIO output (unconnected)
    //
    //  **********************  Development configuration  *********************
    //   Built with desktop Code Composer Studio version 7.2.0.00013
    //******************************************************************************
    #include <msp430.h>
    #include <string.h>
    
    // Forward function declarations
    void Init_CS(void);
    void Init_IO(void);
    void Init_UART(void);
    void Init_eCOMP(void);
    void Software_Trim(void);
    void powerdown(void);
    void powerup(void);
    void put_schar(unsigned char* schar, unsigned int len);
    unsigned int utoa(unsigned int value, unsigned char *sp);
    
    // Project defines
    #define MCLK_FREQ_MHZ 1         // Set MCLK here (1 MHz)
    #define MIN_PULSE_WIDTH 1638    // INT(0.2 * 8192) count for 200 ms
    #define DELAY_6S 49152          // INT(6 * 8192) count for 6 s
    #define DELAY_250ms 2048        // INT(0.25 * 8192) count for 250 ms
    #define NUMofSAMPLES 6          // Number of samples taken to determine the SBC 5V supply is down
    #define STX 2                   // Start of text ASCII character
    #define ETX 3                   // End of text ASCII character
    
    // State flags
    #define POWERED_UP (0x01)       //1 = unit powered up, 0 = unit powered down;
    #define FAILSAFE (0x02)         //1 = FAILSAFE mode, 0 = normal mode;
    #define TxFlag (0x04)           //1 = Serial Tx message pending, 0 = message complete (idle)
    #define RxFlag (0x08)           //1 = Serial Rx message pending, 0 = message complete (idle)
    #define BadMessage (0x10)       //1 = Bad serial message received, 0 = good serial message
    #define Reset_FS_cnt (0x20)     //1 = Request to reset FAILSAFE counter, 0 = disallow reset
    #define SBC_5V_down (0x40)      //1 = SBC 5V supply is down, 0 = SBC 5V supply is up
    #define PULSE_END (0x80)        // 1 = fall edge of FPS detected, 0 = no release of FPS
    
    //*****************************************************************************
    //************************  FRAM persistent variables  ************************
    //*****************************************************************************
    // FRAM persistent variables do not get initialized by the C startup routine,
    // but rather the debug tool chain initializes them for the first time as the
    // application code is loaded onto the target.  These variables are persistent
    // across power cycles.
    #pragma PERSISTENT(FAILSAFE_count)
    unsigned int FAILSAFE_count = 0;
    //*****************************************************************************
    //****************************   Global variables  ****************************
    //*****************************************************************************
    unsigned int state = 0;        // See state flags defined above
    unsigned int SBC_5V_down_counter = 0;   // Counts the number of samples taken on P1.1
    //***************** Front panel switch pulse width variable  ******************
    unsigned int start_pulse;
    unsigned int stop_pulse;
    unsigned int pulse_width;
    //*********************  Serial communication variables  **********************
    int TxMessageLength = 0;
    unsigned char* TxBuff_pointer;
    unsigned char RxBuff;
    //****************** Serial communication characters and message  *************
    unsigned const char version[] = {STX, 'P', 'w', 'r', 'C', 't', 'r', 'l', 'B', 'r', 'd', '-', 'V', '1', '.', '0', '.', '1', '7', '4', '4', ETX};
    unsigned const char prompt[] = {STX, 'A', 'r', 'e', ' ', 'y', 'o', 'u', ' ', 's', 'u', 'r', 'e', ' ', 'y', 'o', 'u', ' ', 'w', 'a', 'n', 't', ' ', 't', 'o', ' ', 'r', 'e', 's', 'e', 't', ' ', 't', 'h', 'e', ' ', 'c', 'o', 'u', 'n', 't', 'e', 'r', '?',' ', '(', 'y', '/', 'n', ')', ETX};
    unsigned const char FSC[] = {STX, 'F', 'A', 'I', 'L', 'S', 'A', 'F', 'E', ' ', 'C', 'o', 'u', 'n', 't', '=', 0};
    unsigned const char ENQ = 5;
    unsigned const char ACK = 6;
    unsigned const char SO = 14;
    unsigned const char DC2 = 18;
    unsigned const char NAK = 21;
    unsigned const char CAN = 24;
    //******************* Previous message variables  *****************************
    unsigned char* Previous_message_pointer = (unsigned char*) &NAK;
    int Previous_message_length = 1;
    
    //******************************************************************************
    //  main - Initialize configuration and run main loop
    //******************************************************************************
    void main(void)
    {
        size_t FSC_length;
        unsigned int index;
        unsigned int cnt_length;
        unsigned int Rx_NAK_count = 0;
        unsigned int Tx_NAK_count = 0;
        unsigned char FSC_message[22];
        unsigned char cnt[6] = {0};
    
        WDTCTL = WDTPW | WDTHOLD;       // Disable watchdog timer
    
        Init_CS();                      // Set up clock systems
        Init_IO();                      // Set up IO ports
        Init_UART();                    // Set up serial communication port
        Init_eCOMP();                   // Set eComp module with timer B0
    
        __bis_SR_register(GIE);         // Interrupts enabled
    
    //********************************** main loop ********************************
        while(1)
        {
            // Check for switch activation
            if(state & PULSE_END)
            {
                state &= ~PULSE_END;
                pulse_width = stop_pulse - start_pulse;
    
                if(pulse_width > MIN_PULSE_WIDTH)   // Pulse must be longer than 200 ms
                {
                    switch (state & POWERED_UP)    // Check the current powered state
                    {
                    case 0:
                        powerup();
                        break;
                    case 1:
                        put_schar((unsigned char*) &DC2, 1);  // Request shutdown
                        break;
                    }
                }
            }
    
            // If FAILSAFE detected, shutdown
            if((state & FAILSAFE) && (state & POWERED_UP))
                powerdown();
    
            // If 5V on the SBC goes down while state is powered up, shutdown main power supply
            if((state & SBC_5V_down) && (state & POWERED_UP))
              powerdown();
    
            // Check for received serial characters
            if(state & RxFlag)
            {
                state &= ~RxFlag;            // Clear Rx flag
                state |= BadMessage;         // Set the Bad message flag
    
                if(RxBuff == 'F')           // Return the FAILSAFE count
                {
                    state &= ~ BadMessage;   // Message is good
                    Tx_NAK_count = 0;        // Allow previous message to be Tx
                    Rx_NAK_count = 0;        // Allow NAKs to be Transmitted
                    cnt_length = utoa(FAILSAFE_count, cnt);
                    FSC_length = strlen((const char*) &FSC);
                    for(index = 0; index < FSC_length; index++)
                    {
                        FSC_message[index] = FSC[index];
                    }
                    for(;index < FSC_length + cnt_length; index++)
                    {
                        FSC_message[index] = cnt[index - FSC_length];
                    }
                    FSC_message[index++] = ETX;
                    put_schar((unsigned char*) &FSC_message, index);
                }
    
                if(RxBuff == '0')           // Return prompt
                {
                    state &= ~ BadMessage;   // Message is good
                    Tx_NAK_count = 0;        // Allow previous message to be Tx
                    Rx_NAK_count = 0;        // Allow NAKs to be Transmitted
                    state |= Reset_FS_cnt;   // Set request to reset FS counter flag
                    put_schar((unsigned char*) &prompt, 51);
                }
    
                if(RxBuff == 'y' || RxBuff == 'Y') // Okay to clear FAILSAFE count
                {
                    state &= ~ BadMessage;   // Message is good
                    Tx_NAK_count = 0;        // Allow previous message to be Tx
                    Rx_NAK_count = 0;        // Allow NAKs to be Transmitted
                    if(state & Reset_FS_cnt)
                    {
                        SYSCFG0 = FRWPPW;        // Program FRAM write enable
                        FAILSAFE_count = 0;      // Reset FAILSAFE counter to zero
                        SYSCFG0 = FRWPPW | PFWP; // Program FRAM write protected (not writable)
                        cnt_length = utoa(FAILSAFE_count, cnt);
                        FSC_length = strlen((const char*) &FSC);
                        for(index = 0; index < FSC_length; index++)
                        {
                            FSC_message[index] = FSC[index];
                        }
                        for(;index < FSC_length + cnt_length; index++)
                        {
                            FSC_message[index] = cnt[index - FSC_length];
                        }
                        FSC_message[index++] = ETX;
                        put_schar((unsigned char*) &FSC_message, index);
                    }
                    state &= ~ Reset_FS_cnt;  // Request to reset FS counter complete, clear flag
                }
    
                if(RxBuff == 'n' || RxBuff == 'N')  // Abort clearing FAILSAFE count
                {
                    state &= ~ BadMessage;   // Message is good
                    Tx_NAK_count = 0;        // Allow previous message to be Tx
                    Rx_NAK_count = 0;        // Allow NAKs to be Transmitted
                    state &= ~ Reset_FS_cnt; // Abort request to reset FS counter
                }
    
                if(RxBuff == ENQ)           // Request for version of PwrCtrlBrd software
                {
                    state &= ~ BadMessage;   // Message is good
                    Tx_NAK_count = 0;        // Allow previous message to be Tx
                    Rx_NAK_count = 0;        // Allow NAKs to be Transmitted
                    put_schar((unsigned char*) &version, 17);
                }
    
                if(RxBuff == NAK)           // Request to repeat previous command
                {
                    state &= ~ BadMessage;   // Message is good
                    Rx_NAK_count = 0;        // Allow NAKs to be Transmitted
                    if(Tx_NAK_count < 5)     // Stop previous message TX after 5 NAKs
                    {
                        put_schar(0, 0);     // Repeat previous command
                        Tx_NAK_count++;
                    }
                }
    
                if(state & BadMessage)      // Received unknown command
                {
                    Tx_NAK_count = 0;       // Allow previous message to be Tx
                    if(Rx_NAK_count < 5)
                    {
                        put_schar((unsigned char*) &NAK, 1);
                        Rx_NAK_count++;
                    }
                }
            }
        }
    }
    
    //******************************************************************************
    //  Init_CS - Initialize configuration of clock systems
    //******************************************************************************
    //  Configure MCLK for 1MHz.
    //  FLL reference clock is REFO.
    //  ACLK = default REFO ~32768Hz.
    //  SMCLK = MCLK = 1MHz.
    //  Use DCO software trim to lock FLL. If FLL is locked and
    //  DCO tap is closest to 256, the DCOFTRIM value is the best one.
    //******************************************************************************
    void Init_CS(void)
    {
        __bis_SR_register(SCG0);            // Disable FLL
        CSCTL3 = SELREF__REFOCLK;           // Set REFO as FLL reference source
        CSCTL1 = DCOFTRIMEN_1 | DCOFTRIM0 | DCOFTRIM1 | DCORSEL_0;  // DCOFTRIM=3,
                                                                    //DCO Range=1MHz
        CSCTL2 = FLLD_0 + 30;               // DCODIV = 1MHz
        __delay_cycles(3);
        __bic_SR_register(SCG0);            // Enable FLL
        Software_Trim();                    // Software Trim to get the best DCOFTRIM value
        CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK;  // set default REFO(~32768Hz)
                                                    // as ACLK source, ACLK = 32768Hz
                                                    // default DCODIV as MCLK and SMCLK source
    }
    
    //******************************************************************************
    //  Init_IO - Initialize configuration of DIO
    //******************************************************************************
    //  P1.0 - Set up as an input to the comparator Channel C0 (FPS sense)
    //  P1.1 - Set up as DIO input to sense +5V from SBC (generates interrupt on low-to-high)
    //  P1.2 - Set up as UART Rx
    //  P1.3 - Set up as UART Tx
    //  P1.4 - Set up as DIO output to drive UART DTR
    //  P1.5 - Set up as DIO input to sense UART DSR
    //  P1.6 - Set up as DIO output to drive low current on-board LED
    //  P1.7 - Set up as DIO output to drive the MPS inhibit signal
    //  P2.0 - Set up as DIO output to test point (comparator output - Cout)
    //  P2.1 - Set up as DIO output to drive LED on FPS
    //  P2.6 - Set up as DIO output (unconnected)
    //  P2.7 - Set up as DIO output (unconnected)
    //******************************************************************************
    void Init_IO(void)
    {
        P1DIR = 0xD8;               // Set direction of pins
        P2DIR = 0xFF;
    
        P1OUT = 0xD0;               // On-board LED on, DTR on, high = MPS off
        P2OUT = 0x02;               // FPS LED high = off
    
        P1IES &= ~BIT1;             // P1.1 interrupt on low-to-high edge
        P1IE |= BIT1;               // P1.1 interrupt enabled
    
        // Configure UART pins
        SYSCFG3 |= USCIARMP;        // Enable remapping
        P1SEL0 |= BIT2 | BIT3;      // Set pins as second function (UART)
    
        // Configure Comparator input & output
        P1SEL0 |= BIT0;       // Select eCOMP input function on P1.0/C0
        P1SEL1 |= BIT0;
        P2DIR |= BIT0;
        P2SEL1 |= BIT0;       // Select CPOUT function on P2.0/COUT
    
        PM5CTL0 &= ~LOCKLPM5;       // Disable the IO power-on default
                                    // high-impedance mode to activate
                                    // previously configured port settings
    }
    
    //******************************************************************************
    //  Init_UART - Initialize configuration of UART
    //******************************************************************************
    //  Baud rate clock = SMCLK (1 MHz)
    //  Divider N = baud rate clock / baud rate => 10^6 / 9600 = 104.1667
    //  Since N is greater than 16, enable the 16 times over sample (UCOS16 = 1)
    //  Now, N = 10^6 / (9600 *16) = 6.51042 => UCA0BRW = INT(6.51042) = 6
    //  First modulation reg (UCBRF0) = INT(16 * REMAIN(6.51042)) = INT(8.167) = 8
    //  Second modulation reg (UCBRS0) = 0x11 - see lookup table 21-4 in User Guide
    //
    //  To change the parameters for the character (Parity, character length, etc.)
    //  Un-comment the appropriate line(s) below
    //******************************************************************************
    void Init_UART(void)
    {
    
        // Configure UART
        UCA0CTLW0 |= UCSWRST;       // Put eUSCI in reset to do configuration
        UCA0CTLW0 |= UCSSEL__SMCLK; // BRCLK source SMCLK
    //*********************** Reset defaults *************************************
    //      Parity - none,
    //      Parity even/odd - NA,
    //      LSB transmitted first,
    //      8-bit character length
    //      One stop bit
    // ************** Un-comment below to set different character format  *********
    //        UCA0CTLW0 |= UCPEN          // Enable Parity
    //        UCA0CTLW0 |= UCPAR__EVEN    // Even Parity
    //        UCA0CTLW0 |= UCPAR__ODD     // Odd Parity
    //        UCA0CTLW0 |= UMSB           // MSB transmitted first
    //        UCA0CTLW0 |= UC7BIT__7BIT   // Enable 7-bit character length
    //        UCA0CTLW0 |= UCSPB          // Enable two stop bits
    //*****************************************************************************
            // Baud Rate calculation
            // Baud Rate = 9600, SMCLK = 1 MHz, over sample is 16
            UCA0BRW = 6;                // Baud rate divider
            UCA0MCTLW = 0x1181;         // UCOS16 = 1 (over sampling enabled)
                                        // UCBRF0 = 8; UCBRS0 = 0x11
    
            UCA0CTLW0 &= ~UCSWRST;      // Initialize eUSCI
            UCA0IE |= UCRXIE;           // Enable USCI_A0 Rx interrupt
    }
    
    //******************************************************************************
    //  Init_eCOMP - Initialize configuration of comparator
    //******************************************************************************
    //  The eCom module is set up so that the Front panel switch on port pin P1.0 is
    //  connected to the positive input of the comparator.  The negative input of the
    //  comparator is connected to the DAC output.  The DAC output is controlled by
    //  two buffers.  Buffer 1 is set for 3/4 of VCC so that the output of the
    //  comparator goes positive only after the positive input is above 3/4 of VCC.
    //  When the comparator output goes high, the DAC output switches to buffer 2.
    //  Buffer 2 is setup for 1/4 of VCC.  Now the positive input must go below 1/4
    //  of VCC for the comparator output to switch back to a low level.  This provides
    //  hysteresis for the switch input.
    //
    //  The output of the comparator is then filtered to further prevent
    //  oscillations in the output due slow slew rate.
    //
    //  The output of the comparator is then connected to both the port pin P2.0 and
    //  the capture/compare block 1.  The capture 1 register is set up to capture both
    //  the rising and falling edges of the comparator output.  The difference
    //  between the rising and falling edges determines how long the switch is pressed.
    //
    //  When the rising edge is detected, it starts the compare block 0.  The
    //  compare block 0 is set to trigger an interrupt 6 seconds after the rising
    //  edge.  If the falling edge occurs before the 6 second compare interrupt
    //  occurs, then the button press is processed normally.  If the 6 second compare
    //  interrupt occurs before the falling edge, then the state changes to the
    //  FAILSAFE mode.
    //******************************************************************************
    void Init_eCOMP(void)
    {
        // Configure reference
          PMMCTL0_H = PMMPW_H;                      // Unlock the PMM registers
          PMMCTL2 |= INTREFEN;                      // Enable internal reference
          __delay_cycles(400);                      // Delay for reference settling
    
          // Setup comparator
          CPCTL0 |= CPPSEL_0;         // Select C0 as input for V+ terminal
          CPCTL0 |= CPNSEL_6;         // Select DAC as input for V- terminal
          CPCTL0 |= CPPEN | CPNEN;    // Enable both eCOMP inputs
          CPDACCTL = CPDACEN;         // Select VCC as reference and enable DAC
          CPDACDATA = 0x1030;         // CPDACBUF1=VCC *3/4   CPDACBUF2=VCC *1/4
          CPCTL1 |= CPFLT | CPFLTDLY_3 | CPMSEL | CPEN;
    //                |         |          |        |--- Turn on eCOMP
    //                |         |          |------------ Low power low speed mode
    //                |         |----------------------- Analog filter delay 3600 ns
    //                |--------------------------------- Enable analog filter
    
        // Setup capture/compare block 0 for compare mode
          TB0CCTL0 |=  CCIS_2;       // Defaults to compare mode and load on write
        //               |------------- Input set to GND
    
        // Setup capture/compare block 1 for capture mode
        TB0CCTL1 |= CM_3 | CCIS_1 | CCIE | CAP | SCS;
        //           |      |        |      |     |---- Synchronous capture
        //           |      |        |      |---------- Capture mode, not compare mode
        //           |      |        |---------------- Enable capture interrupt
        //           |      |------------------------- Capture input CCI0B = eCOMP output
        //           |-------------------------------- Capture both edges
    
        // Timer0_B3 Setup
         TB0CTL |= TBSSEL_1 | ID_2 |  MC_2 | TBCLR;
        //           |         |      |        |---- Clear TB0R and divider logic
        //           |         |      |------------- Timer in continuous mode
        //           |         |-------------------- Input clock divided by 4 (8192 Hz)
        //           |------------------------------ Clock source = ACLK (32768 Hz)
    
    }
    
    //******************************************************************************
    //  Software_Trim - To get the best DCOFTRIM value
    //******************************************************************************
    //  Code provided from TI examples
    //******************************************************************************
    void Software_Trim()
    {
        unsigned int oldDcoTap = 0xffff;
        unsigned int newDcoTap = 0xffff;
        unsigned int newDcoDelta = 0xffff;
        unsigned int bestDcoDelta = 0xffff;
        unsigned int csCtl0Copy = 0;
        unsigned int csCtl1Copy = 0;
        unsigned int csCtl0Read = 0;
        unsigned int csCtl1Read = 0;
        unsigned int dcoFreqTrim = 3;
        unsigned char endLoop = 0;
    
        do
        {
            CSCTL0 = 0x100;                         // DCO Tap = 256
            do
            {
                CSCTL7 &= ~DCOFFG;                  // Clear DCO fault flag
            }while (CSCTL7 & DCOFFG);               // Test DCO fault flag
    
            __delay_cycles((unsigned int)3000 * MCLK_FREQ_MHZ);// Wait FLL lock status (FLLUNLOCK) to be stable
                                                               // Suggest to wait 24 cycles of divided FLL reference clock
            while((CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)) && ((CSCTL7 & DCOFFG) == 0));
    
            csCtl0Read = CSCTL0;                   // Read CSCTL0
            csCtl1Read = CSCTL1;                   // Read CSCTL1
    
            oldDcoTap = newDcoTap;                 // Record DCOTAP value of last time
            newDcoTap = csCtl0Read & 0x01ff;       // Get DCOTAP value of this time
            dcoFreqTrim = (csCtl1Read & 0x0070)>>4;// Get DCOFTRIM value
    
            if(newDcoTap < 256)                    // DCOTAP < 256
            {
                newDcoDelta = 256 - newDcoTap;     // Delta value between DCPTAP and 256
                if((oldDcoTap != 0xffff) && (oldDcoTap >= 256)) // DCOTAP cross 256
                    endLoop = 1;                   // Stop while loop
                else
                {
                    dcoFreqTrim--;
                    CSCTL1 = (csCtl1Read & (~DCOFTRIM)) | (dcoFreqTrim<<4);
                }
            }
            else                                   // DCOTAP >= 256
            {
                newDcoDelta = newDcoTap - 256;     // Delta value between DCPTAP and 256
                if(oldDcoTap < 256)                // DCOTAP cross 256
                    endLoop = 1;                   // Stop while loop
                else
                {
                    dcoFreqTrim++;
                    CSCTL1 = (csCtl1Read & (~DCOFTRIM)) | (dcoFreqTrim<<4);
                }
            }
    
            if(newDcoDelta < bestDcoDelta)         // Record DCOTAP closest to 256
            {
                csCtl0Copy = csCtl0Read;
                csCtl1Copy = csCtl1Read;
                bestDcoDelta = newDcoDelta;
            }
    
        }while(endLoop == 0);                      // Poll until endLoop == 1
    
        CSCTL0 = csCtl0Copy;                       // Reload locked DCOTAP
        CSCTL1 = csCtl1Copy;                       // Reload locked DCOFTRIM
        while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // Poll until FLL is locked
    }
    
    //******************************************************************************
    //  powerdown - Controls hardware pins and changes program state to powered down
    //******************************************************************************
    //  Ensure that the operating system on the SBC is not running by monitoring
    //  the 5 volt supply on the SBC.  When the 5 volt supply is confirmed to be
    //  down, then do the following:
    //  Turn off the main power supply.
    //  Turn off the front panel switch LED
    //  Change program state to powered down
    //
    //  The FAILSAFE mode is also monitored.  If the FAILSAFE is detected, also
    //  shutdown the system.
    //******************************************************************************
    void powerdown(void)
    {
        // Wait for 5V supply on SBC to go down or the FAILSAFE mode
        while(!((state & SBC_5V_down) || (state & FAILSAFE)));
    
        state &= ~(POWERED_UP |SBC_5V_down);  // Clear Flags
    
        P1OUT |= BIT7;          // Turn off the power supply
        P2OUT |= BIT1;          // FPS LED off
    }
    
    //******************************************************************************
    //  powerup - Controls hardware pins and changes program state to powered up
    //******************************************************************************
    //  Turn on the main power supply.
    //  Turn on the front panel switch LED.
    //  Change program state to powered up.
    //  An infinite loop is entered.  The loop exits if the FAILSAFE mode is detected.
    //
    //  Normally the loop will exit by receiving an <ENQ> character from the SBC,
    //  after it is completely booted.  When the ENQ is received, the reply string is
    //  sent by over the serial link and the loop is exited.
    //
    //  If a character other than ENQ is received, a NAK is sent back to have the
    //  command from the SBC repeated.  After five consecutive NAK are sent, the loop
    //  is exited on the next unknown character received.
    //******************************************************************************
    void powerup(void)
    {
        int Tx_NAK_count = 0;
        int delay = 760;
    
        P1OUT &= ~BIT7;          // Turn on the power supply
        P2OUT &= ~BIT1;          // FPS LED on
        state |= POWERED_UP;    // Now in the on state
        state &= ~ SBC_5V_down;  // Clear Flag from previous down state
        TB0CCTL1 &= ~CCIE;  // Disable FPS interrupts while waiting
    
        // Delay approximately 760 ms to allow the 5V on the SBC to come up.
        // Measured delay between enabling the MPS and the active signal for
        // the 5 V supply on the SBC is 380 ms.  Providing 100% margin gives
        // 760 ms.
        while (delay--)
        {
            __delay_cycles(1000);
        }
    
        // There is a special case where the FPS can be pressed repeatedly in
        // rapid succession which causes the SBC to fail to boot correctly.
        // Even though the MPS is up and running.  So this section of code
        // sets up the ISR to check if the SBC 5V is still down.  If so,
        // the SBC_5V_down flag will be set and the MPS is turn off to
        // synchronize the state of the power control board with the SBC.
        if(P1IN & BIT1)
        {
            TB0CCR2 = TB0R + DELAY_250ms;   // Read timer and add delay to compare 2
            TB0CCTL2 &=  ~CCIFG;            // Ensure no compare 2 interrupt is pending
            TB0CCTL2 |=  CCIE;              // Enable compare 2 interrupt
        }
    
        TB0CCTL0 &=  ~CCIFG;    // Ensure no interrupt is pending
        TB0CCTL1 |= CCIE;       // Enable FPS interrupts while waiting
    
        while(1)
        {
            if((state & SBC_5V_down) || (state & FAILSAFE))  // Exit loop if FAILSAFE or SBC is off
            {
                state &= ~(POWERED_UP | SBC_5V_down);  // Clear Flags
                P1OUT |= BIT7;          // Turn off the power supply
                P2OUT |= BIT1;          // FPS LED off
                break;
            }
    
    
            if(state & RxFlag)          // Wait for ENQ from SBC
            {
                state &= ~RxFlag;
                if(RxBuff == ENQ)
                {
                    put_schar((unsigned char*) &version, 17);
                    break;
                }
                else                 // Unknown command, request repeat command
                {
                    if(Tx_NAK_count < 5)    //Transmit a NAK up to five times
                    {
                        put_schar((unsigned char*) &NAK, 1);
                        Tx_NAK_count++;
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
        state &= ~PULSE_END;    //Clear any FPS activation
    }
    
    //******************************************************************************
    //  put_schar - Transmit a character to the serial communication port
    //******************************************************************************
    //  If arguments are zero, retransmit previous message.
    //  Set the length of message to be sent.
    //  Put character into Tx buffer used by the ISR.
    //  Set the Tx flag to indicate that a transmission is in progress.
    //  Enable interrupt. Since the UART Tx register is empty, an interrupt occurs
    //  immediately.  Loop until message is completely sent.
    //******************************************************************************
    void put_schar(unsigned char* schar, unsigned int len)
    {
        if(schar == 0 && len == 0)
        {
            TxMessageLength = Previous_message_length;
            TxBuff_pointer = Previous_message_pointer;
        }
        else
        {
            if(*schar != NAK)
            {
                Previous_message_length = len;
                Previous_message_pointer = schar;
            }
            TxMessageLength = len;
            TxBuff_pointer = schar;
        }
        state |= TxFlag;
        UCA0IE |= UCTXIE;             // Enable USCI_A0 Tx interrupt
        while(state & TxFlag);        // TxFlag cleared by the ISR
    }
    
    
    //******************************************************************************
    //  utoa - Convert an unsigned integer into a decimal ASCII string
    //******************************************************************************
    //  value is the unsigned integer to be converted
    //  sp is a pointer to the string buffer where the characters are placed
    //  returns the length of the string
    //******************************************************************************
    unsigned int utoa(unsigned int value, unsigned char *sp)
    {
        char tmp[16];
        char *tp = tmp;
        unsigned int i, len;
    
        while (value || tp == tmp)
        {
            i = value % 10;
            value /= 10;
            if (i < 10)
              *tp++ = i + '0';
        }
    
        len = tp - tmp;
    
        while (tp > tmp)
            *sp++ = *--tp;
    
        return len;
    }
    
    //******************************************************************************
    //*******************************  ISRs   **************************************
    //******************************************************************************
    // UART ISR
    //******************************************************************************
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=USCI_A0_VECTOR
    __interrupt void USCI_A0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
        switch(__even_in_range(UCA0IV,USCI_UART_UCTXCPTIFG))
        {
            case USCI_NONE:
                break;
            case USCI_UART_UCRXIFG:
                RxBuff = UCA0RXBUF;
                state |= RxFlag;           // Set flag that a char has been received
                break;
            case USCI_UART_UCTXIFG:
                UCA0TXBUF = *TxBuff_pointer;
                TxMessageLength--;
                if(TxMessageLength == 0)
                {
                    state &= ~TxFlag;       // Clear flag to indicate completion of Tx
                    UCA0IE &= ~UCTXIE;      // Disable USCI_A0 TX interrupt
                }
                else
                {
                    TxBuff_pointer++;
                }
                break;
            case USCI_UART_UCSTTIFG:
                break;
            case USCI_UART_UCTXCPTIFG:
                break;
        }
    }
    //******************************************************************************
    // Port 1 interrupt service routine
    //******************************************************************************
    //  A high-to-low transition on port pin 1.6 (the SBC 5V sensing signal) creates
    //  an interrupt.  Once this transition is detected, a timer is set up to
    //  sample the 5V signal every 250 ms.  When the 250 ms delay expires, the
    //  compare 2 ISR is called.  The compare 2 ISR is set up to take multiple
    //  sample of the 5V signal.
    //******************************************************************************
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=PORT1_VECTOR
    __interrupt void Port_1(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(PORT1_VECTOR))) Port_1 (void)
    #else
    #error Compiler not supported!
    #endif
    {
        P1IFG &= ~BIT1;                 // Clear P1.1 IFG
        TB0CCR2 = TB0R + DELAY_250ms;   // Read timer and add delay to compare 2
        TB0CCTL2 &=  ~CCIFG;            // Ensure no compare 2 interrupt is pending
        TB0CCTL2 |=  CCIE;              // Enable compare 2 interrupt
    }
    //******************************************************************************
    // Timer B0 CCR0, interrupt service routine
    //******************************************************************************
    //  This is the highest priority timer interrupt.  It is used for the FAILSAFE
    //  mode.  The number of times this ISR is called is counted for off line
    //  service analysis.
    //******************************************************************************
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = TIMER0_B0_VECTOR
    __interrupt void Timer_B (void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER0_B0_VECTOR))) Timer_B (void)
    #else
    #error Compiler not supported!
    #endif
    {
        state |= FAILSAFE;            // Set FAILSAFE flag
        SYSCFG0 = FRWPPW;             // Program FRAM write enable
        FAILSAFE_count++;             // Count the number of times FAILSAFE occurs
        SYSCFG0 = FRWPPW | PFWP;      // Program FRAM write protected (not writable)
        TB0CCTL0 &=  ~CCIE;           // Disable compare interrupt
    }
    //******************************************************************************
    // Timer0_B1 CCR1 and CCR2, interrupt service routine
    //******************************************************************************
    //  CCR1 is used to capture the FPS activation.  The rising edge is captured
    //  and starts the CCR0 to interrupt in 6 seconds.  If the fall edge is captured
    //  before the CCR0 interrupt occurs, then the fall edge timer value is captured
    //  and the CCR0 interrupt is disabled.  This is a normal FPS activation.  If
    //  the CCR0 interrupt occurs before the fall edge, then the FAILSAFE mode is
    //  set.  On the detection of the fall edge after FAILSAFE mode is handled in
    //  the background tasks, the FAILSAFE flag is cleared.
    //
    //  CCR2 is used to sample the SBC_5V signal multiple (6) times at a rate of
    //  250 ms.  If the SBC_5V signal is low each time, the state flag
    //  SBC_5V_down is set.  This flag is monitored by the background tasks.  This
    //  flag is cleared by the background tasks: powerdown and powerup.
    //******************************************************************************
    #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:
                if(!(TB0CCTL1 & COV))                   // No overflow
                {
                    if((TB0CCTL1 & CCI) == CCI)         // Rising edge interrupt
                    {
                        start_pulse = TB0CCR1;
                        TB0CCR0 = start_pulse + DELAY_6S; // Compare interrupt in 6 seconds
                        TB0CCTL0 &=  ~CCIFG;             // Ensure no interrupt is pending
                        TB0CCTL0 |=  CCIE;              // Enable compare interrupt
                    }
                    else                                // Falling edge interrupt
                    {
                        if(state & FAILSAFE)
                        {
                            state &= ~(FAILSAFE | PULSE_END);  // Clear Flags
                        }
                        else
                        {
                            state |= PULSE_END;
                            stop_pulse = TB0CCR1;
                            TB0CCTL0 &=  ~CCIFG;        // Ensure no interrupt is pending
                            TB0CCTL0 &=  ~CCIE;         // Disable compare interrupt
                        }
                    }
                }
                else    // Clear overflow
                {
                    TB0CCTL1 &= ~COV;
                }
                break;
            case TB0IV_TBCCR2:              // CCR2 check to ensure SBC 5V supply is still down
                if(SBC_5V_down_counter < NUMofSAMPLES)
                {
                    if(P1IN & BIT1)
                    {
                        SBC_5V_down_counter++;
                        TB0CCR2 = TB0R + DELAY_250ms;   // Read timer and add delay to compare 2
                        TB0CCTL2 &=  ~CCIFG;            // Ensure no compare 2 interrupt is pending
                    }
                    else
                    {
                        SBC_5V_down_counter = 0;    // Reset counter
                        TB0CCTL2 &=  ~CCIE;         // Disable compare 2 interrupt
                    }
                }
                else
                {
                    state |= SBC_5V_down;       // Set flag
                    SBC_5V_down_counter = 0;    // Reset counter
                    TB0CCTL2 &=  ~CCIE;         // Disable compare 2 interrupt
                }
                break;
            case TB0IV_TBIFG:
                break;                               // overflow
            default:
                break;
        }
    }

  • Hi David,

    I'll look further into the code. Have you tested any chips that failed when you toggle the input to P1.0 only by connecting it to VCC and GND on the target board? If so, can you send the assembly lot code on the failed parts and see if it is different from the good parts or send a picture showing the numbers on the failed parts' packages?

    If not, can you measure the current going through R22 when it is connected to the FR2111 on both a good and bad device when the FPS is on?

    Thanks,

    Ryan

  • Hi Ryan,

    To answer your question, have I tested any chips that failed when P1.0 is toggled between VCC and GND, I decided to connect a simple pushbutton with a pull-down 10 kΩ resistor to the evaluation board and test a few chips.  I can send you a picture of the evaluation board wired with the simple pushbutton if that would be helpful in any way.  The results of testing three chips with this configuration is one failed and two passed. 

    Using the chips that just came in, the chips used on the previous build, and the build prior to the last build, the following codes are the code from these chips. All of these lots have some chips that worked and some chips that failed to work.

    YMS code = 75TG4 Lot code = CC7D B

     YMS code = 75TG4 Lot code = CFEF B

    YMS code = 6ATG4 Lot code = C29D B

    So, there does not seems to be a relationship between the lot and the failures.

  • Hi David,

    Thank you for performing the tests! Please do send a picture of the push button setup. I would like to confirm that the device with the failed comparator from the push button test has not been connected to your custom board before testing with the push button. Is this correct?

    Thanks,
    Ryan
  •  Hi Ryan,

    Yes, the evaluation board is powered by MSP-FET and the pushbutton and pull-down resistor are only connected to signals on the evaluation board.  Please see the attached picture. 

  • Hi David,

    I received sample FR2111 parts and was able to reproduce the issue you are seeing. After looking deeper into the control code for your board, I found that CPNSEL in the CPCTL0 register is being set to 111b which turns out to be a reserved value. This happens because CPCTL0 has a reset value of 0x0100 and all assignments to the register in the code use the “|=” operator, causing CPNSEL to be set to 111b instead of 110b during initialization. Changing the first "|=" to "=" clears the '1' from reset and sets CPCTL0 as expected. The code in Init_eCOMP function should then look like this:

          // Setup comparator
          CPCTL0 = CPPSEL_0;         // Select C0 as input for V+ terminal
          CPCTL0 |= CPNSEL_6;         // Select DAC as input for V- terminal
          CPCTL0 |= CPPEN | CPNEN;    // Enable both eCOMP inputs
          CPDACCTL = CPDACEN;         // Select VCC as reference and enable DAC
          CPDACDATA = 0x1030;         // CPDACBUF1=VCC *3/4   CPDACBUF2=VCC *1/4
          CPCTL1 |= CPFLT | CPFLTDLY_3 | CPMSEL | CPEN;
    //                |         |          |        |--- Turn on eCOMP
    //                |         |          |------------ Low power low speed mode
    //                |         |----------------------- Analog filter delay 3.6 ms
    //                |--------------------------------- Enable analog filter
    

    After retesting the affected chips, this has solved the behavior. When CPNSEL is set to the reserved value, it is connected to an internal channel for testing that works in test mode but is left floating during normal operation, so the behavior becomes unpredictable. 

    Thanks,

    Ryan

**Attention** This is a public forum