Skip to main content
RLind.3
Associate III
May 30, 2022 2:45 AM UTC
Question

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

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. :smiling_face_with_smiling_eyes:

Thanks,

Rebecca

This topic has been closed for replies.

5 replies

KDJEM.1
ST Technical Moderator
Jun 1, 2022 4:02 PM UTC

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 "Best answer" on the reply which solved your issue or answered your question.
Piranha
Principal III
Jun 1, 2022 7:35 PM UTC

> low power mode (GPIO clock disabled)

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

Piranha
Principal III
Jun 1, 2022 10:21 PM UTC

> 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.

RLind.3
RLind.3Author
Associate III
Jun 2, 2022 12:41 AM UTC

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