cancel
Showing results for 
Search instead for 
Did you mean: 

What is the right sequence to enable under-drive mode in STM32F779NI ?

bivin mato
Associate III

Hello,

I'm not able to enable MR under-drive mode in my STM32F779NI chip.

The exact problem is UDRDY is not getting set -> Line number 39 to 43.

Below is the code snippet. Any suggestion would be very helpful. Thanks in advance.

int main(void)
{
	/* Add your application code here */
	__IO uint32_t tmpreg;
 
	/* Enable clock for toggle LED */
	SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOIEN);
	tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOIEN);
 
	/* Enable clock for switch input (EXTI) */
	SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
	tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
 
	/* Enable clock for SYSCFG that connects switch to EXTI */
	SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN);
	tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN);
 
	/* Enable clock for PWR module */
	SET_BIT(RCC->APB1ENR, RCC_APB1ENR_PWREN);
    tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_PWREN);
 
	/* Configure toggle LED */
	GPIOI->MODER |= GPIO_MODER_MODER15_0;
	GPIOI->PUPDR |= GPIO_PUPDR_PUPDR15_0;
	GPIOI->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR15;
	GPIOI->BSRR= GPIO_BSRR_BS15; // Reset
 
	/* Configure switch input */
	GPIOC->PUPDR = 0;
	GPIOC->MODER = 0;
	SYSCFG->EXTICR[3] = 0x20;
	EXTI->IMR = 0x2000;
	EXTI->EMR = 0;
	EXTI->RTSR = 0x2000;
 
	NVIC_SetPriority(EXTI15_10_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 2, 0));
	NVIC_EnableIRQ(EXTI15_10_IRQn);
 
	SET_BIT(PWR->CR1, PWR_CR1_MRUDS);
 
	PWR->CR1 |= PWR_CR1_UDEN;
 
	while( ! ((READ_BIT(PWR->CSR1, PWR_CSR1_UDRDY)) == PWR_CSR1_UDRDY ) );
 
	/* Infinite loop */
	while (1)
	{
		/* Set SLEEPDEEP bit of Cortex System Control Register */
		SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
 
		/* Ensure that all instructions done before entering SLEEP mode */
		__DSB();
		__ISB();
 
		/* Request Wait For Interrupt */
		__WFI();
 
		/* Reset SLEEPDEEP bit of Cortex System Control Register */
		SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
	}
}

Regards,

Bivin

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

It looks like UDRDY bits get set only when the CPU enters stop mode. You can check for and clear them after it wakes back up.

0693W000000Wo6hQAC.png

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

3 REPLIES 3
TDK
Guru

It looks like UDRDY bits get set only when the CPU enters stop mode. You can check for and clear them after it wakes back up.

0693W000000Wo6hQAC.png

If you feel a post has answered your question, please click "Accept as Solution".

Sorry. I overlooked this information. Thanks a lot ! :)

Regards

Bivin

But the HAL library for PWRex itself has a check wait loop for this flag field . But luckily with a timeout :grinning_face: .

HAL_StatusTypeDef HAL_PWREx_EnterUnderDriveSTOPMode(uint32_t Regulator, uint8_t STOPEntry)
{
  uint32_t tempreg = 0;
  uint32_t tickstart = 0;
  
  /* Check the parameters */
  assert_param(IS_PWR_REGULATOR_UNDERDRIVE(Regulator));
  assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
  
  /* Enable Power ctrl clock */
  __HAL_RCC_PWR_CLK_ENABLE();
  /* Enable the Under-drive Mode ---------------------------------------------*/
  /* Clear Under-drive flag */
  __HAL_PWR_CLEAR_ODRUDR_FLAG();
  
  /* Enable the Under-drive */ 
  __HAL_PWR_UNDERDRIVE_ENABLE();
 
  /* Get tick */
  tickstart = HAL_GetTick();
 
  /* Wait for UnderDrive mode is ready */
  while(__HAL_PWR_GET_FLAG(PWR_FLAG_UDRDY))
  {
    if((HAL_GetTick() - tickstart ) > PWR_UDERDRIVE_TIMEOUT_VALUE)
    {
      return HAL_TIMEOUT;
    }
  }
  
  /* Select the regulator state in STOP mode ---------------------------------*/
  tempreg = PWR->CR1;
  /* Clear PDDS, LPDS, MRLUDS and LPLUDS bits */
  tempreg &= (uint32_t)~(PWR_CR1_PDDS | PWR_CR1_LPDS | PWR_CR1_LPUDS | PWR_CR1_MRUDS);
  
  /* Set LPDS, MRLUDS and LPLUDS bits according to PWR_Regulator value */
  tempreg |= Regulator;
  
  /* Store the new value */
  PWR->CR1 = tempreg;
  
  /* Set SLEEPDEEP bit of Cortex System Control Register */
  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
  
  /* Select STOP mode entry --------------------------------------------------*/
  if(STOPEntry == PWR_SLEEPENTRY_WFI)
  {   
    /* Request Wait For Interrupt */
    __WFI();
  }
  else
  {
    /* Request Wait For Event */
    __WFE();
  }
  /* Reset SLEEPDEEP bit of Cortex System Control Register */
  SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
 
  return HAL_OK;  
}