Why not entering DeepStandby?

Hi,

S7G2 and SSP 1.1.3 and can not upgrade at this time.

The following routine used to work for me to enter DeepStandby.  It no longer does.  The PCB has changed, but not in any areas that I see relevent to DeepStandby.  The TP_TOGGLE()'s merely toggle a GPIO pin.  Except for the toggling of TP3 at entry to this routine, the only toggling that takes place is that of TP2 each iteration of the loop in this routine.

In short, I'm not entering DeepStandby, but none of the HAL g_lpm calls fail and return err != SSP_SUCCESS.  How can I determine why g_lpm_lowPowerMode.p_api->lowPowerModeEnter() fails?

 

Steve

 PS - sorry about the lack of format below.  I attempted to use use the source tool, but clearly I failed.

static void DeepStandbyNow()
{
ssp_err_t err;
uint32_t wupen_preSleep = 0;

TP_TOGGLE(3);
TP_TOGGLE(3);

err = g_lpm_lowPowerMode.p_api->init(g_lpm_lowPowerMode.p_cfg);

if (err != SSP_SUCCESS)
{
TP_TOGGLE(2);
TP_TOGGLE(3);
TP_TOGGLE(3);
TP_TOGGLE(3);
TP_TOGGLE(3);
TP_TOGGLE(3);
TP_TOGGLE(3);
TP_TOGGLE(2);
__BKPT(0);
}

// g_lpm_lowPowerMode.p_api->deepStandbyCancelRequestEnable(LPM_DEEP_STANDBY_IRQ11_DS, LPM_CANCEL_REQUEST_EDGE_FALLING);
g_lpm_lowPowerMode.p_api->deepStandbyCancelRequestEnable(LPM_DEEP_STANDBY_IRQ13_DS, LPM_CANCEL_REQUEST_EDGE_RISING);
g_lpm_lowPowerMode.p_api->wupenGet( &wupen_preSleep );
g_lpm_lowPowerMode.p_api->wupenSet(0);
// wupen_preSleep |= (1 << 11); // enable IRQ11
wupen_preSleep |= (1 << 13); // enable IRQ13
g_lpm_lowPowerMode.p_api->wupenSet(wupen_preSleep);

while (1)
{
TP_TOGGLE(2);
TP_TOGGLE(2);

err = g_lpm_lowPowerMode.p_api->lowPowerCfg(
LPM_LOW_POWER_MODE_DEEP, // lpm_low_power_mode_t
LPM_OUTPUT_PORT_ENABLE_RETAIN, // lpm_output_port_enable_t
LPM_POWER_SUPPLY_DEEPCUT0, // lpm_power_supply_t
LPM_IO_PORT_NO_CHANGE); // LPM_IO_PORT_NO_CHANGE

if (err != SSP_SUCCESS)
{
TP_TOGGLE(2);
TP_TOGGLE(3);
TP_TOGGLE(3);
TP_TOGGLE(2);
__BKPT(0);
}

err = g_lpm_lowPowerMode.p_api->lowPowerModeEnter();

if (err != SSP_SUCCESS)
{
TP_TOGGLE(2);
TP_TOGGLE(3);
TP_TOGGLE(3);
TP_TOGGLE(3);
TP_TOGGLE(3);
TP_TOGGLE(2);
__BKPT(0);
}

tx_thread_sleep (10);
}

} // DeepStandbyNow()

  • Background: the routine listed above is in a thread dedicated to entering low power mode. Upon thread startup, which is automatic, the entry routine calls the following. Commenting out the line that executes the core functionality of the routine did not make a difference. (IE the //SJG line)

    static void DeepStandbyCheck(void)
    {
    /* Check if the device has just left Deep Software Standby mode. */
    //SJG if (1U == R_SYSTEM->RSTSR0_b.DPSRSTF)
    {
    uint16_t current_prcr_value;

    /* Clear the Deep Software Standby Reset flag */
    R_SYSTEM->RSTSR0_b.DPSRSTF = 0U;

    /* Gain access to Deep Software Standby registers to clear
    * the interrupt enable and flag for IRQ11 and RTC Interval.
    * This was the IRQ used to wake the device.
    * The Deep Software Standby registers are write protected.
    */

    /* Read the current value */
    current_prcr_value = R_SYSTEM->PRCR;
    /* Set the password of A5xx and set bit 2 */
    current_prcr_value |= (PRCR_KEY << 8) | PRCR_ACCESS;
    /* Write value back to PRCR to gain access */
    R_SYSTEM->PRCR = current_prcr_value;

    R_SYSTEM->DPSIER1_b.DIRQ13E = 0U; // P0_9 (accelerometer) IRQ13-DS

    do { R_SYSTEM->DPSIFR1_b.DIRQ13F = 0U; } while (R_SYSTEM->DPSIFR1_b.DIRQ13F != 0U);

    * In this example "Maintain the IO port states" is selected
    * so clear the IOKEEP bit.
    */
    R_SYSTEM->DSPBYCR_b.IOKEEP = 0U;

    /* Turn register protect back on */
    current_prcr_value &= (uint16_t)~PRCR_ACCESS;
    current_prcr_value |= PRCR_KEY << 8;
    R_SYSTEM->PRCR = current_prcr_value;
    }
    } // DeepStandbyCheck()
  • In reply to Steve:

    Hi Steve,

    Are you sure that IRQ13 is not "immediately" waking up the device?

    Regards,
    adboc
  • In reply to adboc:

    Hi adboc,

    Thanks for writing, Yes, I'm sure. I've a logic analyzer on several items in the system, IRQ13 included. I see periodic I2C activity from another thread and I TP2 toggling from the top of the while loop in my first post. It toggles every 100ms, just as expected from the sleep(10) at the end of that loop.

    Steve
  • In reply to Steve:

    Hi Steve,

    Please could you verify that before entering low power mode required conditions are met?

    Moreover, to make low power modes and debugger working together, please verify if debugger has enabled Low Power Mode Handling, for Deep SW Standby mode a debugger script is also required (please note if you're looking at proper project):

     

    1425.CM_low_power_debug.JLinkScript.txt
    void clear_DBIRQ(void)
    {
    	JLINK_CORESIGHT_WriteDP(2, (1 << 24) | (0 << 4));  // Select AP[1], bank 0
    	JLINK_CORESIGHT_WriteAP(0, (0) | (2 << 0) | (1 << 31)); // AP-access size. Fixed to 2: 32-bit  // Enable software access to the Debug APB bus.
    	JLINK_CORESIGHT_WriteAP(1, 0x80000410); //MCUCTRL register
    	JLINK_CORESIGHT_WriteAP(3, 0x00000000); //Clear DBIRQ bit
    	
    	JLINK_MEM_WriteU16(0x4001E3FE, 0xA502);  // PRCR register. Enable access to SYOCDCR register
    	JLINK_MEM_WriteU8(0x4001E40E, 0x80);    // SYOCDR register, set DBGEN bit
    	JLINK_MEM_WriteU16(0x4001E3FE, 0xA500);  // PRCR register. Disable access to SYOCDCR register
    }
    
    void InitTarget(void) 
    {
    	clear_DBIRQ();
    }
      
    void SetupTarget(void)
    {
    	clear_DBIRQ();
    }

    Regards,
    adboc

  • In reply to adboc:

    The debugger is out of the picture for me, I think, because I'm running SSP1.1.3

    Silly question: how does one access SBYCR.SSBY and DPSBYCR.DPSBY?
  • In reply to Steve:

    Hello Steve,

    If you just need to read values in debug mode, you may view these ones in IO Registers tab:

    If you would like to write to these registers, you must first unlock register access (the same code you've already have):

    /* Read the current value */
    current_prcr_value = R_SYSTEM->PRCR;
    /* Set the password of A5xx and set bit 2 */
    current_prcr_value |= (PRCR_KEY << 8) | PRCR_ACCESS;
    /* Write value back to PRCR to gain access */
    R_SYSTEM->PRCR = current_prcr_value;

    Then you can access SBYCR and DPSBYCR:

    R_SYSTEM->SBYCR (or R_SYSTEM->SBYCR_b.<pin-name>)
    R_SYSTEM->DPSBYCR (or R_SYSTEM->DPSBYCR_b.<pin-name>)

    At the end, you should lock the register:

    /* Turn register protect back on */
    current_prcr_value &= (uint16_t)~PRCR_ACCESS;
    current_prcr_value |= PRCR_KEY << 8;
    R_SYSTEM->PRCR = current_prcr_value;

    Regards,
    adboc

  • In reply to adboc:

    Thanks. SBYCR and DPSBYCR are 0xC000 and 0xC0 respectively.

    (Even with SPP 1.1.3 I think it works to set a breakpoint at the g_lpm_lowPowerMode.p_api->lowPowerModeEnter() call? That's how I grabbed these values.)

    Steve
  • In reply to Steve:

    Hi Steve,

    I've tried to reproduce the issue on SK-S7G2, SSP 1.1.3. I've applied Low Power Mode settings (Low Power Handling and Script file) to debug configuration (Run > Debug configurations... > %Your-project-name% > Debugger tab > Connection tab).

    CPU configured to wake up on IRQ11 (S4 user button) instead of IRQ13. It is reset each time S4 is pressed.

    Could you verify your project using a different cancelling source (e.g. another IRQ)?

    Please find my project: S7_SK_DeepSoftwareStandby_1_1_3.zip

    Regards,
    adboc