cancel
Showing results for 
Search instead for 
Did you mean: 

STM32WLE Standby Mode Pull Up/Down Registers - PWR_PUCRx vs GPIOx_PUPDR

RLind.3
Associate III

Hi there,

I am trying to set PU/PD resistors that will stay set while my STM32WLE is in Standby mode. Am I correct in saying that I need to use the PWR_PUCRx registers to keep the PU/PD resistors active while in Standby? If so, is there anything else that could catch me out? Eg, do I need to reset the GPIOx_PUPDR registers? Can I use the PWR_PUCRx registers while in Run mode, or should I only use the GPIOx_PUPDR registers while running?

A brief explanation of PWR_PUCRx vs GPIOx_PUPDR would be greatly appreciated. 😊

Thanks,

Rebecca

5 REPLIES 5
KDJEM.1
ST Employee

Hi @RLind.3​ ,

In Standby mode, for STM32WLE, you need the PWR_PUCRx registers to keep the PU resistors active and the PWR_PDCRx registers to keep the PD resistors active. There should be no constraints if you use PWR_PUCRx  or PWR_PDCRx registers in run mode. However their main purpose is to allow pull-up or pull down while being in a low power mode (GPIO clock disabled). 

We can add that, the GPIOx_PUPDR is only one register for pull-up/pull-down resistors while you have PWR_PUCR (Power pull-up control register) dedicated for pull-up resistors and PWR_PDCR (Power pull-down control register) dedicated for pull-up resistors. Also, please note that the I/O pull-up and pull-down configurations defined in the PWR_PUCRx and PWR_PDCRx registers are applied only when APC bit is set in PWR control register 3. 

Does this answer your question?

Kaouthar

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

> low power mode (GPIO clock disabled)

Those two are unrelated and the "explanation" in parentheses is confusing.

Hi @KDJEM.1​ ,

Thanks for your reply and explanation.

I have been doing some tests with the STM32WLE and I have found some unexpected behaviours:

  • When I use only the GPIOx_PUPDR register and enter standby, the PU/PD resistors are kept - checking the voltages with a multimeter shows they are pulled high/low as set in GPIOx_PUPDR.
  • When I set the APC bit and use the PWR_PUCRx/PWR_PDCRx registers, there is an additional 2mA drawn when I enter standby. I disabled all GPIOx_PUPDR resistors before using the PWR_PUCRx/PWR_PDCRx ones. I have checked my PU/PD configuration and it is equivalent to the GPIOx_PUPDR one I used previously.

The C1SBF in PWR_EXTSCR is set when I wake from Standby so I believe I am entering it correctly. I clear C1SBF each time the MCU wakes up.

Do you have any clues as to these behaviours?

Thanks,

Rebecca

Piranha
Chief II

> there is an additional 2mA drawn when I enter standby

When entering low-power mode, set DBGMCU_CR to zero and disconnect the debugger physically.

> When I use only the GPIOx_PUPDR register and enter standby, the PU/PD resistors are kept

Show the code, which enters the low-power mode and configures wake-up features.

Hi @Piranha​ ,

Thank you for your advice. I have set DBGMCU_CR to zero and that has fixed the problem of excessive current.

Here is my standby_begin() function:

void standby_begin(void)
{
    // Keep SRAM2
    PWR->CR3 |= PWR_CR3_RRS;
 
    // Enable WKUP1 pin PA0
    PWR->CR3 |= PWR_CR3_EWUP1;
    PWR->CR4 &= ~PWR_CR4_WP1; // Rising edge
 
    // Set SLEEPDEEP bit
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
 
    // Set to enter standby
    PWR->CR1 &= ~PWR_CR1_LPMS;
    PWR->CR1 |= PWR_LOWPOWERMODE_STANDBY;
 
    // Change to periodic sampling of VDD
    PWR->CR3 |= PWR_CR3_ULPEN;
 
    // Wait for radio to finish (if not under reset)
    if (!(RCC->CSR & RCC_CSR_RFRST))
    {
        while((PWR->SR2 & PWR_SR2_RFBUSYMS) && (PWR->SR2 & PWR_SR2_RFBUSYS));
 
        // Shutdown radio
        RCC->CSR |= RCC_CSR_RFRST;
    }
 
    // Clear wake up flags
    PWR->SCR |= 0x4907; // Clear all flags
 
    // Set all GPIO to input
    GPIOA->MODER = 0x00;
    GPIOB->MODER = 0x00;
    GPIOC->MODER = 0x00;
 
    // Set all GPIO to pull down except LEDs, ADC input, SWDIO, OSC32, WKUP1
    GPIOA->PUPDR = 0xA556AAA4; // 1010 0101 0101 1010 1010 1010 1010 0100
    GPIOB->PUPDR = 0xAAA95AAA; // 1010 1010 1010 1001 0101 1010 1010 1010
    GPIOC->PUPDR = 0x0AAAAAAA;
 
        // Use PWR PU/PD instead of GPIOx
//      PWR->PDCRA = 0xC3F4; // 1100 0011 1111 0100
//      PWR->PDCRB = 0x1035; // 0001 0000 0011 0101
//      PWR->PDCRC = 0x3FFF; // 0011 1111 1111 1111
//      PWR->PUCRA = 0x3C0A; // 0011 1100 0000 1010
//      PWR->PUCRB = 0x01C0; // 0000 0001 1100 0000
//      PWR->PUCRC = 0x0000;
//
//      GPIOA->PUPDR = 0x00;
//      GPIOB->PUPDR = 0x00;
//      GPIOC->PUPDR = 0x00;
//      PWR->CR3 |= PWR_CR3_APC;
 
    // Disable debugging in LP modes
    DBGMCU->CR = 0;
 
    // Disable RTC alarm interrupt
    NVIC_DisableIRQ(RTC_Alarm_IRQn);
    NVIC_ClearPendingIRQ(RTC_Alarm_IRQn);
 
    // Disable radio interrupt
    NVIC_DisableIRQ(SUBGHZ_Radio_IRQn);
    NVIC_ClearPendingIRQ(SUBGHZ_Radio_IRQn);
 
    // Disable ADC interrupt
    NVIC_DisableIRQ(ADC_IRQn);
    NVIC_ClearPendingIRQ(ADC_IRQn);
 
    // Disable TIM1 interrupt
    NVIC_DisableIRQ(TIM1_CC_IRQn);
    NVIC_ClearPendingIRQ(TIM1_CC_IRQn);
 
   // Disable low power timer interrupts
    NVIC_DisableIRQ(LPTIM1_IRQn);
    NVIC_ClearPendingIRQ(LPTIM1_IRQn);
    NVIC_DisableIRQ(LPTIM2_IRQn);
    NVIC_ClearPendingIRQ(LPTIM2_IRQn);
    NVIC_DisableIRQ(LPTIM3_IRQn);
    NVIC_ClearPendingIRQ(LPTIM3_IRQn);
 
    // Disable SysTick and interrupt
    SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
    NVIC_ClearPendingIRQ(SysTick_IRQn);
 
    watchdog_kick();
 
     // Check low power regulator is ready
     while((PWR->SR2 & PWR_SR2_REGLPS) == 0);
 
    // Enter standby
    __WFI();
}

Please let me know if you need any other code or information.

Thanks,

Rebecca