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.

Device sometimes locks up when going into Halt LPM mode

Other Parts Discussed in Thread: TMS320F28335

I need some help.

I'm using a TMS320F28335 in a battery powered device and I need to enter halt mode when the device is not in use to conserve battery power.

Randomly, the device seems to get stuck when going into halt mode, (maybe ~5% of the time).

Haven't been able to figure out why it's happening.  

 

Here's where I'm setting the LPM mode before entering the main loop:

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

// Write the LPM code value

    EALLOW;

if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 1) // Only enter low power mode when PLL is not in limp mode.

{

      SysCtrlRegs.LPMCR0.bit.LPM = 0x0002;   // LPM mode = Halt

}

EDIS;

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

 

Here's where I enter LPM mode.  This is called upon either by a button press or a timeout.

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

void go2sleep(void)

{

PieCtrlRegs.PIEIER1.bit.INTx6 = 0;                            //disable adc int

//PieCtrlRegs.PIEIER8.bit.INTx1 = 1;                          //disable I2C int 

PieCtrlRegs.PIEIER4.bit.INTx1 = 0;                            //disable ECAP isr   

AllOff();                                                                               //turn off all device indicators

SetLEDState(LED_GREEN, LED_BLINK2);              //let user know it's still alive

 if(vib_enabled)Quickbuzz(3);        //beep or buzz to confirm entering LPM mode                             

 else Quickbeep(5);  

DELAY_US(100000);    

asm("  EALLOW");

//SysCtrlRegs.WDCR = 0x006F;                                 //Disable Watchdog

//Power-down the ADC

SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 0;

//AdcRegs.ADCTRL2.bit.ADCBGPWD = 0;

AdcRegs.ADCTRL3.bit.ADCPWDN = 0;

//AdcRegs.ADCTRL2.bit.ADCREFPWD = 0;

//SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 0;

 

//Turn-off clocks

SysCtrlRegs.PCLKCR0.all = 0;

SysCtrlRegs.PCLKCR1.all = 0;

SysCtrlRegs.PCLKCR3.all = 0;

//Enable all pull-ups

GpioCtrlRegs.GPAPUD.all = 0;                                        // The pullups have to be enabled to minimize the 

GpioCtrlRegs.GPBPUD.all = 0;                                        // leakage currents, thereby the HALT mode current

// stays within the spec quoted in the datasheet.

EALLOW;

//Write the LPM code value 

if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 1)             // Only enter low power mode when PLL is not in limp mode.

{

      SysCtrlRegs.LPMCR0.bit.LPM = 0x0002;            // LPM mode = Halt

 }

EDIS;

//FlashRegs.FPWR.bit.PWR = FLASH_SLEEP;       // Put the Flash to sleep   

//asm(" RPT #7 || NOP"); 

//asm(" EDIS");

// Force device into HALT

asm(" IDLE");                                                             // Device waits in IDLE until falling edge on GPIO pin  wakes device from halt mode

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

 

Here's the wake interrupt which is triggered from one of the port A IO pins

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

interrupt void WAKE_ISR(void)

{

asm("  EALLOW");

//undo what was done in go2sleep()

SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;

AdcRegs.ADCTRL3.bit.ADCPWDN = 1;

SysCtrlRegs.PCLKCR0.all = 0xFD3C;

SysCtrlRegs.PCLKCR1.all = 0xFF3F;

SysCtrlRegs.PCLKCR3.all = 0x3F00;

GpioCtrlRegs.GPAPUD.all = 0x00000FDF;

GpioCtrlRegs.GPBPUD.all = 0;

//FlashRegs.FPWR.bit.PWR = 0;  

asm(" EDIS");

DELAY_US(100000);

if(vib_enabled)Quickbuzz(3); //beep or buzz to confirm coming out of LPM

else Quickbeep(4);

sleepflag=0;

sleeptimer=0;

//AllOff();

timer2flag=1; //go into pwr LED handling

PieCtrlRegs.PIEIER1.bit.INTx6 = 1; //enable adc int

PieCtrlRegs.PIEIER4.bit.INTx1 = 1; //enable ECAP isr

PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE

//PieCtrlRegs.PIEACK.bit.ACK1 = 1;

 SetLEDState(LED_GREEN, LED_ON);

}

......................................................................................................................................
I can't tell if it's getting hung up going into or coming out of LPM.  I'd appreciate any tips.  Thanks in advance.

 

  • Hi Jason,

    Let me know if I am overlooking this in the code.  I don't see where the WAKEINT is enabled.  We have a code example (Example_2833xHaltWake.c) in controlSUITE that performs a similar process.   This could be a good reference.

    -Devin

     

  • I didn't want to post too much code but below is all of the initialization before the main loop where WAKEINT is enabled.  The LPM mode seems to work a majority of the time.  I can go into and out of halt mode.  Occasionally, it will get stuck.  I was hoping something obvious would stand out.  It's been difficult to pinpoint exactly where the freeze occurs since my connection gets hosed up when the device freezes.  Here is the code, thanks:

     

    int main(int argc, char *argv[])

    {

    // Initialize System Control:

    // PLL, WatchDog, enable Peripheral Clocks

     

       InitSysCtrl();

     

       EALLOW;

       #define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)   = 25.0 MHz

       EDIS;

     

    // Clear all interrupts and initialize PIE vector table:

    // Disable CPU interrupts

       DINT;

     

    // Initialize the PIE control registers to their default state.

    // The default state is all PIE interrupts disabled and flags

    // are cleared.

    // This function is found in the DSP2833x_PieCtrl.c file.

       InitPieCtrl();

       InitI2CGpio();

    // Disable CPU interrupts and clear all CPU interrupt flags:

       IER = 0x0000;

       IFR = 0x0000;

     

    // Initialize the PIE vector table with pointers to the shell Interrupt

    // Service Routines (ISR).

    // This will populate the entire table, even if the interrupt

    // is not used in this example.  This is useful for debug purposes

    // The shell ISR routines are found in DSP2833x_DefaultIsr.c.

    // This function is found in DSP2833x_PieVect.c.

       InitPieVectTable();

     

    // Interrupts that are used in this example are re-mapped to

    // ISR functions found within this file.

       EALLOW;  // This is needed to write to EALLOW protected register

       PieVectTable.ADCINT = &adc_isr;

       PieVectTable.I2CINT1A = &i2c_int1a_isr;

       PieVectTable.TINT2 = &cpu_timer2_isr;

       PieVectTable.XINT13 = &cpu_timer1_isr;

       PieVectTable.ECAP1_INT = &ecap1_isr;

       PieVectTable.WAKEINT = &WAKE_ISR;

       EDIS;    // This is needed to disable write to EALLOW protected registers

     

    // Step 4. Initialize all the Device Peripherals:

    // This function is found in DSP2833x_InitPeripherals.c

    // InitPeripherals(); // Not required for this example

     

    // Copy time critical code and Flash setup code to RAM

    // This includes the following ISR functions: epwm1_timer_isr(), epwm2_timer_isr()

    // epwm3_timer_isr and and InitFlash();

    // The  RamfuncsLoadStart, RamfuncsLoadEnd, and RamfuncsRunStart

    // symbols are created by the linker. Refer to the F28335.cmd file.

       //MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);

     

    // Call Flash Initialization to setup flash waitstates

    // This function must reside in RAM

       //InitFlash();

       SetupGPIO();

       InitECapture();

       InitECap1Gpio();

       I2C_Init();

       InitObjects();

       InitSpiaGpio();

       InitScibGpio();

       DAC_WTM();

       //ConfigDigipot();

    // Step 5. User specific code, enable interrupts:

       InitCpuTimers();

       ConfigCpuTimer(&CpuTimer1, 150, 10); //10us

       ConfigCpuTimer(&CpuTimer2, 150, 1000000);   //1 sec 

       GpioDataRegs.GPACLEAR.bit.GPIO0 = 1; //disable buzzer until PWM initialized

    // To ensure precise timing, use write-only instructions to write to the entire register. Therefore, if any

    // of the configuration bits are changed in ConfigCpuTimer and InitCpuTimers (in DSP2833x_CpuTimers.h), the

    // below settings must also be updated.

    // Enable ADCINT in PIE

       CpuTimer2Regs.TCR.all = 0x4001;

       CpuTimer1Regs.TCR.all = 0x4001; 

       PieCtrlRegs.PIEIER1.bit.INTx6 = 1;

       // Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1

       PieCtrlRegs.PIEIER8.bit.INTx1 = 1;   

    // Enable eCAP INTn in the PIE: Group 3 interrupt 1-6

       PieCtrlRegs.PIEIER4.bit.INTx1 = 1;

     

     // Enable WAKEINT in the PIE: Group 1 interrupt 8

       PieCtrlRegs.PIEIER1.bit.INTx8 = 1;

       PieCtrlRegs.PIEACK.bit.ACK1 = 1;

     

       IER |= M_INT1; //timer 0

       IER |= M_INT13;  //timer 1

       IER |= M_INT8;

       IER |= M_INT14; //timer 2

       IER |= M_INT4; //ECAP

       EINT;          // Enable Global interrupt INTM

       ERTM;          // Enable Global realtime interrupt DBGM

     

       // Write the LPM code value

        EALLOW;

    if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 1) // Only enter low power mode when PLL is not in limp mode.

    {

          SysCtrlRegs.LPMCR0.bit.LPM = 0x0002;   // LPM mode = Halt

        }

        EDIS;

     

    GasGauge.reg[2] = 0xFF;

    GasGauge.reg[3] = 0xFF;

    InitProx();

        ConfigureADC();

        InitAdc();  // Init the ADC

        InitEPwm1();

        scia_fifo_init();

    scia_echoback_init();

       init_power();

       Init_LEDs();

       Init_Accel();

       AllOff();

     

    if(GpioDataRegs.GPCDAT.bit.GPIO73 == 0) //special mode to reset GG, mute button pressed when powering up

    {

    WriteGGRegister(2,0xFF);

    while(I2cMsgOut1.MsgStatus != I2C_MSGSTAT_INACTIVE&&I2cMsgOut1.MsgStatus != I2C_MSGSTAT_SEND_WITHSTOP);

    WriteGGRegister(3,0xFF);

    while(I2cMsgOut1.MsgStatus != I2C_MSGSTAT_INACTIVE&&I2cMsgOut1.MsgStatus != I2C_MSGSTAT_SEND_WITHSTOP);

    Quickbeep(1);

    }

    if(GpioDataRegs.GPCDAT.bit.GPIO72 == 0) //special mode to disable LPM counter

    {

    LPM_enabled = false;

    Quickbeep(1);

    }

     

    if(vib_enabled)Quickbuzz(3);

    else Quickbeep(4);

     

    autoWindow();

    zeroFlag = 1;

     

    // Wait for interrut

       for(;;)

       {

       }

  • Jason,

    It could be that the device is not coming out of HALT mode. We have never seen an instance when the device is unable to enter HALT mode (unless the wakeup signal is noisy and pulls the device out of HALT right away). You could easily confirm if the device is in HALT by the drop in current requirement. Not usre if this is possible if the board is already designed and there is no hook to stick a meter in. if there is a ferrite bead in series with the supply lines, you could remove it and stick a meter in. If the wakeup signal is noisy, it may lead to the part being stuck in HALT. Please ensure the pin used for wakeup is noise-free both while entering and exiting HALT.

  • Hareesh,

     

    I added a filter cap to the wake line and so far it seems to be working fine.  

     

    Thanks,

     

    Jason

  • jason,

    thanks for the feedback. Did you ascertain if the device is unable to (i) get into HALT mode or (ii) come out of it? What value cap did you use?

     

    Hareesh

  • I wasn't able to confirm whether the processor successfully got into halt or not.  I had a surface mount 22UF cap lying around so I used that.  There's no resistor in front of it, only a long trace to a switch and pullup resistor.

  • Hi, 

    I'm using the processor for a similar application, controlling a unit that runs on batteries and need to consume as little power as possible. 

    I'm testing out putting it strictly into LPM (HALT)  by using the example code from TI, with a couple of modifications. But essentially, its that code. The chip itself is on a board with few components (a few switches connected to the IO pins, and the passive components recommended by the data sheet) and is powered by a standard lab bench power supply. Im getting an estimate of power consumption by watching the current draw from the power supply. Heres what I'm seeing:

    Start the code in a debug session, and the current draw is about 0.08 - 0.10 A. (this is the same if I put the code into flash and run with the debugger disconnected.)

    Flip a switch, connected to an IO pin, to put it in sleep mode, current draw drops to 0.04 A

    Flip another switch from high to low to wake up the processor, current draw drops back up to 0.08 - 0.10 A. 

    So that leads me to believe its entering some kind of low power mode. What I'm concerned with, however, is that I'm not putting it in a state where the absolute least amount of power is being used. Ideally, I'd like to see the current drop to 0, or .01, depending on the resolution of the power supply. Is this possible? Or am I seeing the lowest power draw already and need to accept that.

    Thanks for any responses!

    - Jon 

  • Jon,

    You have not clarified which low-power mode you are using. "Sleep" does not mean much. For your application, it appears you should be using the HALT mode. In this mode, the total current consumption should be < 100 uA at room temperature. Since the HALT mode current is primarily leakage current, it will increase with temperature. Based on the number you are reporting (40 mA), it does not appear you are in HALT mode. Even in HALT, the current consumption will not drop to zero.

  • Thanks for getting back to me. Correct, I did infer that I was attempting to put the processor in the HALT mode when I first mentioned that I was using a LPM. I would agree that it does not appear I'm in the halt mode, I guess my question is, since I'm using the TI example code designed to put the processor into HALT mode, what do I have to do to get the device in the HALT mode? 

  • The example should work "as is". If the EALLOW is active, all it takes to put a device into HALT is to write 0x0002 in LPMCR2 and execute the IDLE instruction (after powering down the flash). It could be that some pin is waking up the device as soon as it goes into HALT. Have you configured any pin for wakeup? Could you try this on a board where all I/O pins are left unconnected?