Tool/software: Code Composer Studio
Hello Team,
I am assisting a customer to figure out why on some MSP430FR2111 chips the eCOMP does not work as intended. Below is the customers setup :
" The front panel switch (FPS) is debounced by the set-reset flip flop. The output of the set-reset flip flop is low when the FPS is inactive and high when the FPS is active. The signal from the flip flop is routed to P1.0 (pin 2 on the MSP430FR2111IPW16R). The function selection registers (P1SEL0, P1SEL1, P2SEL0, & P2SEL1) are set to connect P1.0 to C0 of the eCOMP module. The output of the eCOMP module is routed to P2.0.
The issue is that they have the input P1.0 is working correctly. When read P1IN BIT0 (P1.0) the signal behaves as expected. Pressing the FPS the signal goes high and release the FPS and the signal goes low. They verified this by commenting out the configure of the eCOMP and running a main loop that turns on LEDs if the FPS is pressed and turns the LEDs off when the FPS is released.
They also measured the voltage on P1.0 and found it to go from 0 V to 3.3 V as expected. That is the signal levels are not in some indeterminate state or voltage level.
The eCOMP module is configured so that when the C0 (P1.0) signal is less than 2.475 V, the output of the comparator should be low (0 V). When the C0 signal is greater than 2.475 V, the output of the comparator should be high (3.3 V). However, as soon as the eCOMP module is configured and the module selected, the output of the comparator is high (3.3 V). This is the wrong output level. Not sure why this is happening. Pressing the FPS has no effect. The output of the comparator stays high.
Of the six boards that were built only one worked on the first test. The other five boards had the issue with the comparator. After trying several different things, I decided to replace one of the MSP430. After replacing the MSP430, the board started working. Encouraged by this success they replaced two more MSP430s. One worked, but the other had the same issue with the comparator. At this point they had 3 working boards and 3 non-working boards.
They then replaced the MSP430 on the remaining 3 non-working boards. This includes the one board that they just replaced the MSP430 on. Out of the 3 non-working boards, only one started working. The board that that started working was the board they had previously replaced the MSP430 on. It was the third time they replaced the MSP430 on that board. Now it works.
Although we do take ESD precautions, the customer feels that this might be an ESD issue. However, it seems unlikely that random ESD events would cause exactly the same failure in these chips. Since both good and bad chips seem to be coming off of the same cut tape, it seems unlikely to be a process issue with the IC. "
At this point, the customer has four working boards and two non-working boards. They are trying to understand what is causing this problem. So it can be prevented in the future. The boards have been powered up carefully. For example the front panel switch is always connected before power is applied. Furthermore, the serial port is not plugged until the power is applied. Power comes from the MSP-FET430UIF.
Is this a known issue that you'll are aware of ? I found nothing specific to this in the errata.
Thank you for your time.
Sincerely,
Kishen
/****************************************************************************** * The following code shows how I am setting up the eCOMP module. * The main clock is running at 1 MHz. * * The comment header for the subroutine Init_eCOMP to see how the eCOMP module * is configured. * * I run the main loop in one of two ways. When the registers configuration of * P1SEL0, P1SEL1, P2SEL0, and P2SEL1 are commented out, the while loop check * the front panel switch (FPS) to see if it is active. If it is active, three * different LEDs are turned on. If the FPS is inactive, all LEDs are turned * off. * * When the P1.0 is configured to drive the eCOMP (the registers configuration of * P1SEL0, P1SEL1, P2SEL0, and P2SEL1 are not commented out), the while loop * always reads P1.0 as low. Which is okay, as the P1.0 signal is routed to the * positive input of the comparator. The output of the comparator is * routed to P2.0. P2.0 should output a low signal. Out of six boards, one * works correctly and the other five to not. * * I understand that there is likely a board problem, but the only reason for * the P2.0 output to be high is when P1.0 is greater than 2.475 volts. Which * is not the case. The input signal P1.0 is low as can be verified by checking * the signal on pin 2. *****************************************************************************/ #include <msp430.h> #define MCLK_FREQ_MHZ 1 // Set MCLK here (1 MHz) // Forward function declarations void Init_CS(void); void Init_eCOMP(void); void Software_Trim(void); //***************************************************************************** //************************ 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; int main(void) { unsigned int FS_temp = 0xE; WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer Init_CS(); // Set system clock Init_eCOMP(); // Set up comparator 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 // Configure Comparator input & output P1SEL0 |= BIT0; // Select 3rd module function P1SEL1 |= BIT0; // eCOMP input function on P1.0/C0 P2DIR |= BIT0; P2SEL0 &= BIT0; // Select 2nd module function P2SEL1 |= BIT0; // Select CPOUT function on P2.0/COUT PM5CTL0 &= ~LOCKLPM5; while(1) // Capture loop { if(P1IN & BIT0) { P1OUT |= BIT6; // On-board LED on P1OUT &= ~BIT7; // MPS LED on P2OUT &= ~BIT1; // FPS LED on } else { P1OUT &= ~BIT6; // On-board LED off P1OUT |= BIT7; // MPS LED off P2OUT |= BIT1; // FPS LED off } } } //****************************************************************************** // 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_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 to switch bounce. // // 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 start 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 3.6 ms // |--------------------------------- 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 by 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 }