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.

TMS570LS1224: SafetyDiag + LowPowerMode issue

Part Number: TMS570LS1224

Hello,

This question refers to safety diagnostic in correlation with low power mode.

During implementation Low Power Modes on TMS570LS1224 I found out (with  help) that I can't switch into low power mode for some configurations (QJ Wang noticed that there could be an issue with PBIST in sys_startup source file. It looked like mcu switch to lower power mode and cannot wake up... When he commented out big part of safety checks code and than Low Power Mode works.

Now I investigate further and in the result I know that there are some safety functions which should be disabled if I would like to use low power mode functionality. In the picture below you can see my working configuration (with this config I can successfully wake up) . If I check e.g. MIBSPI1 or HET low power mode will crash (cannot wake up). What is the reason of that? Is it possible to add these safety checks and work with low power modes?

    /* Wakeup Interrupt: RTI compare 0 */
        vimREG->WAKEMASKCLR0 = 0xFFFFFFFF;
        vimREG->WAKEMASKCLR1 = 0xFFFFFFFF;
        vimREG->WAKEMASKCLR2 = 0xFFFFFFFF;
        vimREG->WAKEMASKSET0 = (1U << 2U)   /* RTI CAP0 */
                             | (1U << 23U)  /* GPIO Low */
                             | (1U << 16U); /* CAN1 High */

/* Flash */ flashWREG->FPAC2 = 0x7; flashWREG->FMAC = 0x6; flashWREG->FBAC = 0x70F; flashWREG->FMAC = 0x0; flashWREG->FBAC = 0x70F; /* Setup flash bank power modes */ flashWREG->FBFALLBACK = 0x00000000U | (uint32)((uint32)SYS_SLEEP << 14U) /* BANK 7 */ | (uint32)((uint32)SYS_SLEEP << 0U); /* BANK 0 */ /* Flash Charge Pump Fallback Power Mode */ flashWREG->FPAC1 &= (1UL << 0); /* Enter DOZE MODE */ /* Reset RTI Counter 0 */ rtiStopCounter(rtiCOUNTER_BLOCK0); rtiResetCounter(rtiCOUNTER_BLOCK0); /* Clock RTI using OSCIN */ systemREG1->RCLKSRC = 0x0; /* Wake up time setup */ rtiREG1->CMP[0U].COMPx = 30000000U; rtiREG1->CMP[0U].UDCPx = 30000000U; rtiREG1->INTFLAG = 0x0007000FU; rtiREG1->CLEARINTENA = 0x00070F0FU; rtiREG1->SETINTENA = rtiNOTIFICATION_COMPARE0; /* Start counter 0 */ rtiStartCounter(rtiCOUNTER_BLOCK0); /** - Setup GCLK, HCLK and VCLK clock source for normal operation, power down mode and after wakeup */ systemREG1->GHVSRC = (uint32)((uint32)SYS_OSC << 24U) | (uint32)((uint32)SYS_OSC << 16U) | (uint32)((uint32)SYS_PLL1 << 0U); systemREG1->CSDISSET = 0xFE; systemREG1->CDDISSET = 0xFFBF; asm(" NOP"); asm(" NOP"); asm(" NOP"); asm(" WFI"); asm(" NOP"); asm(" NOP"); asm(" NOP"); asm(" NOP");

Below my post wake up code:

    systemREG1->CSDISCLR = 0x31;

    /* Reconfigure flash bank/pump fallback modes to be "active" */
    flashWREG->FBFALLBACK = 0x00000000U
                          | (uint32)((uint32)SYS_ACTIVE << 14U) /* BANK 7 */
                          | (uint32)((uint32)SYS_ACTIVE << 0U); /* BANK 0 */

    mapClocks();

  • Hi Michal,

    I will look into this and get back to you later today.

    Regards, Sunil

  • Michal,

    I am able to make the part enter doze mode even with every safety diagnostic check enabled (except for CPU and CCM self-tests). Did you remember to disable monitoring of the main oscillator? You are disabling all clock sources except for the main oscillator, so the clock monitor will detect an "oscillator failure" and switch the clock domains over to the HF LPO clock source, which has been disabled. This leads to a state where the code is trying to execute using an unavailable clock source, and would need an external safety monitor such as a watchdog PMIC to reset the part.

    /* Disable oscillator monitoring to prevent detection of osc fail */
    systemREG1->CLKTEST = 0x010A0000;

    Regards, Sunil

  • Hi Michal,

    I am pasting the code to enter doze mode:

    int main(void)
    {
    /* USER CODE BEGIN (3) */
    
        unsigned int command;
    
        /* Initialize RTI, clocked by OSCIN / 2 = 8MHz, generates compare 0 interrupt / wakeup every 1 second */
        rtiInit();
    
        /* Initialize GIO: GIOB[2], pin 142 used as wakeup source, GIOA[1:0] used to choose LPM */
        gioInit();
    
        /* Enable CPU response to interrupt requests */
        _enable_interrupt_();
    
        while(1)
        {
            command = gioGetPort(gioPORTA) & 0x3;       // read GIOA[1:0] port status
    
            if (command == 0x0)
            {
                /* stay active */
            }
            else
            {
                /* GIOA[1:0] configured to enter one of the low-power modes */
    
                /* set up flash pump active grace period as 7 HCLK/16 cycles */
                flashWREG->FPAC2 = 0x7;
    
                /* Bank 7 */
                flashWREG->FMAC = 0x6;
                flashWREG->FBAC = 0x70F;
    
                /* Bank 0 */
                flashWREG->FMAC = 0x0;
                flashWREG->FBAC = 0x70F;
    
                /* Setup flash module to change fallback modes for banks/pump to be "sleep" */
                flashWREG->FBFALLBACK = 0x00000000U
                                      | (uint32)((uint32)SYS_SLEEP << 14U) /* BANK 7 */
                                      | (uint32)((uint32)SYS_SLEEP << 2U)  /* BANK 1 */
                                      | (uint32)((uint32)SYS_SLEEP << 0U); /* BANK 0 */
    
                /* Disable oscillator monitoring to prevent detection of osc fail */
                systemREG1->CLKTEST = 0x010A0000;
    
                /* Enter a low-power mode depending on GIOA[1:0] */
                if (command == DOZE)
                {
                    enter_doze();                           // wake up via RTI clocked by OSCIN
                }
                else if (command == SNOOZE)
                {
                    enter_snooze();                         // wake up via RTI clocked by LF LPO
                }
                else
                {
                    enter_sleep();                          // wake up only via GIOB[2] rising edge
                }
                post_wakeup();
    
            }
        }
    
    /* USER CODE END */
    
        return 0;
    }
    
    
    /* USER CODE BEGIN (4) */
    
    void enter_doze(void)
    {
        /* RTI is configured to generate compare 0 interrupt every 10 seconds using 16MHz OSCIN as source */
        /* Reset and restart RTI Counter 0 */
        rtiStopCounter(rtiCOUNTER_BLOCK0);
        rtiResetCounter(rtiCOUNTER_BLOCK0);
    
        /** - Clear all pending interrupts */
        rtiREG1->INTFLAG = 0x0007000FU;
    
        /** - Disable all interrupts */
        rtiREG1->CLEARINTENA = 0x00070F0FU;
    
        /** - Enable RTI Compare 0 Interrupt **/
        rtiREG1->SETINTENA = rtiNOTIFICATION_COMPARE0;
    
        /* Start counter 0 */
        rtiStartCounter(rtiCOUNTER_BLOCK0);
    
        /** - Setup GCLK, HCLK and VCLK clock source for normal operation, power down mode and after wakeup */
        systemREG1->GHVSRC = (uint32)((uint32)SYS_OSC << 24U)
                           | (uint32)((uint32)SYS_OSC << 16U)
                           | (uint32)((uint32)SYS_PLL1 << 0U);
    
        /* turn off all clock sources except main oscillator */
        systemREG1->CSDISSET = 0xFE;
    
        /* turn off all clock domains except RTICLK */
        systemREG1->CDDISSET = 0xFFBF;
    
        asm(" WFI");
        asm(" nop");
        asm(" nop");
        asm(" nop");
        asm(" nop");
    }
    
    void post_wakeup(void)
    {
        /* toggle GIOA[7] for signaling wake-up */
        gioSetPort(gioPORTA, gioGetPort(gioPORTA)^0x80);    // toggle GIOA[7]
    
        /* Restart main oscillator, LF LPO and HF LPO first */
        systemREG1->CSDISCLR = 0x31;
    
        /* Configure PLLs based on original configuration */
        /**   - Setup pll control register 1:
        *     - Setup reset on oscillator slip
        *     - Setup bypass on pll slip
        *     - setup Pll output clock divider to max before Lock
        *     - Setup reset on oscillator fail
        *     - Setup reference clock divider
        *     - Setup Pll multiplier
        */
        systemREG1->PLLCTL1 =  (uint32)0x00000000U
                            |  (uint32)0x20000000U
                            |  (uint32)((uint32)0x1FU << 24U)
                            |  (uint32)0x00000000U
                            |  (uint32)((uint32)(6U - 1U)<< 16U)
                            |  (uint32)((uint32)(165U - 1U)<< 8U);
    
        /**   - Setup pll control register 2
        *     - Setup spreading rate
        *     - Setup bandwidth adjustment
        *     - Setup internal Pll output divider
        *     - Setup spreading amount
        */
        systemREG1->PLLCTL2 =  (uint32)((uint32)255U << 22U)
                            |  (uint32)((uint32)7U << 12U)
                            |  (uint32)((uint32)(2U - 1U) << 9U)
                            |  (uint32)61U;
    
        /* Restart all other clock sources. All clock domains are enabled automatically. */
        systemREG1->CSDISCLR = 0xFF;
    
        /* Reconfigure flash bank/pump fallback modes to be "active" */
        /** - Setup flash bank power modes */
        flashWREG->FBFALLBACK = 0x00000000U
                              | (uint32)((uint32)SYS_ACTIVE << 14U) /* BANK 7 */
                              | (uint32)((uint32)SYS_ACTIVE << 2U)  /* BANK 1 */
                              | (uint32)((uint32)SYS_ACTIVE << 0U); /* BANK 0 */
    
    
        /* Restore original clock source/domain bindings */
        mapClocks();
    
        /* Resume oscillator monitoring */
        systemREG1->CLKTEST = 0x000A0000;
    
    }
    

  • Sunil,

    I added to my code 'Disable and enable oscillator monitoring' but still have problem with wake up (using RTI) when Some of Memory Built-In Self test are enabled..

    In your code, inside post_wakeup() you setup PLLCTL1, PLLCTL2, and then use mapClocks(); What is the reason to do that? In mapClocks() you there is also setup of PLLCTL1 and 2.

  • Michal,

    mapClocks() only configures the final divider stage in the PLL control register. The configuration of the other dividers is done outside of this function by the setupPLL() function.

    As an experiment, can you update the pbistStop() function to be like the below:

    void pbistStop(void)
    {
    /* USER CODE BEGIN (20) */
    
        pbistREG->PACT = 0x0U;
        systemREG1->MSTGCR &= 0xFFFFFFF0U;
        systemREG1->MSTGCR |= 0xAU;
        systemREG1->MSTGCR &= 0xFFFFFFF0U;
        systemREG1->MSTGCR |= 0x5U;
    
    #if 0
    
    /* USER CODE END */
        /* disable pbist clocks and ROM clock */
        pbistREG->PACT = 0x0U;
        systemREG1->MSTGCR &= 0xFFFFFFF0U;
        systemREG1->MSTGCR |= 0x5U;
    /* USER CODE BEGIN (21) */
    
    #endif
    
    /* USER CODE END */
    }

    Regards, Sunil

  • Michal,

    Were you able to set up your entry/exit to/from doze mode correctly?

    Regards, Sunil