cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 PVD not interrupting

MaxMax
Associate II

Hi,

I want to get the PVD on a STM32H743 running in order to write some data to the flash, which did not work for whatever reason. So, as a first step, I tried to implement an interrupt which just pulls a GPIO-pin high and check it with an oscilloscope. I configured "PVD Level 6" (2.85V) and "External Interrupt Mode with Rising Edge Trigger Detection" in CubeMX, and implemented HAL_PWR_PVDCallback() with a GPIO_Write. However, when I disconnect the power supply, the pin is not being pulled high. The duration in which the power drops from 2.85V to 1.6V is approx. 10ms, which I guess should be plenty of time to process the interrupt. I can fire the interrupt with a software trigger (SWIER1) on EXTI line 16 successfully, which tells me that the EXTI interrupt is working in principle. I also checked that PVDE in PWR_CR1 is enabled, as well as the PLS bits for the threshold.

The following code was generated by CubeMX in stm32h7xx_hal_msp.c:

void HAL_MspInit(void)
{
  /* USER CODE BEGIN MspInit 0 */
 
  /* USER CODE END MspInit 0 */
  PWR_PVDTypeDef sConfigPVD = {0};
 
  __HAL_RCC_SYSCFG_CLK_ENABLE();
 
  /* System interrupt init*/
  /* PendSV_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(PendSV_IRQn, 15, 0);
 
  /* Peripheral interrupt init */
  /* PVD_AVD_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(PVD_AVD_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(PVD_AVD_IRQn);
 
  /** PVD Configuration 
  */
  sConfigPVD.PVDLevel = PWR_PVDLEVEL_7;
  sConfigPVD.Mode = PWR_PVD_MODE_IT_RISING;
  HAL_PWR_ConfigPVD(&sConfigPVD);
  /** Enable the PVD Output 
  */
  HAL_PWR_EnablePVD();
 
  /* USER CODE BEGIN MspInit 1 */
 
  /* USER CODE END MspInit 1 */
}

Unfortunately I can't change the supply voltage other than disconnecting it, which makes it hard to check the registers at the time PVD is supposed to detect the power drop.

Is there anything I missed or misunderstood?

9 REPLIES 9
alessandro morniroli
Associate III

Hi,

did you resolve?

I have the same problem running an STM32F429NI board.

I'm trying the same code as above (I'm also calling __HAL_RCC_PWR_CLK_ENABLE prior to set PVD registers).

No matter what, the interrupt is not triggering (in the ISR I'm driving a GPIO to high level, but I'm not able to see it changing the status). As MaxMax, I can fire the interrupt with a software trigger (SWIER1) on EXTI line 16 successfully, which tells me that the EXTI interrupt is working in principle.

VDD and VDDA are on the same power bus, and it takes approximately 4.2ms to drop from 3V to 1.8V (I'm running 160Mhz clock, so 4ms should be enough to move a GPIO).

0693W000008zBS0QAM.pngAny clue?

Read out and check/post content of PWR_CR.

Running a trivial program, which after setup does nothing but in a loop checks PWR_CSR.PVDO and e.g. outputs its value to a pin, should also indicate whether this flag gets active upon power going down.

You may also try disconnect the power supply and use a regulated power supply to try to set the lower voltage level deliberately.

Do you use Brownout Detection (i.e. what's the value of FLASH_OPTCR.BOR_LEV)?

JW

alessandro morniroli
Associate III

Hi, thanks for the support and the advices.

So, here is my full code.

int main(void)
{
  uint32_t         registers[4];
  PWR_PVDTypeDef   config              = { 0 };
  GPIO_InitTypeDef init                = { 0 };
  RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
  RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
 
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_SYSCFG_CLK_ENABLE();
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
  __HAL_FLASH_DATA_CACHE_ENABLE();
  __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 160;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
 
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
 
  memset (&config, 0x00, sizeof (config));
 
  config.Mode     = PWR_PVD_MODE_IT_RISING_FALLING;
  config.PVDLevel = PWR_CR_PLS_LEV7;
 
  HAL_PWR_ConfigPVD (&config);
 
  HAL_PWR_EnablePVD ();
 
  HAL_NVIC_SetPriority (PVD_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ (PVD_IRQn);
 
  SystemClock_Config();
 
  init.Pin   = GPIO_PIN_12;
  init.Mode  = GPIO_MODE_OUTPUT_PP;
  init.Pull  = GPIO_NOPULL;
  init.Speed = GPIO_SPEED_FREQ_LOW;
 
  HAL_GPIO_Init(GPIOA, &init);
 
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
 
  __enable_irq();
 
  registers[0] = PWR->CR;
  registers[1] = EXTI->IMR;
  registers[2] = EXTI->FTSR;
  registers[3] = EXTI->RTSR;
 
  (void) registers;
 
  while (1)
  {
      if (PWR->CSR & PWR_CSR_PVDO)
      {
          HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET);
      }
      else
      {
          HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
      }
  }
}

1) contents of PWR_CR and EXTI registers seems correct.

0693W000008zC6UQAU.png0693W000008zC8zQAE.png0693W000008zC9JQAU.png2) I'm checking PVDO output using GPIO but it's not moving. Flag never gets active;

3) Brownout is disabled

0693W000008zCAMQA2.png 

4) my last chance, trying to bypass switching power circuit of the board and using a regulated power supply directly connected to VDD/VDDA. I'll give it a try, but I think I will not resolve.

alessandro morniroli
Associate III

I've tried also using regulated power supply (3v3). It seems that CPU is resetting almost immediatly as voltage drop down to 3V: shouldn't be 1V8?

I'll try an EVB, maybe it's an hardware problem of my board.

alessandro morniroli
Associate III

With NUCLEO F429ZI seems to work. I think I should investigate on my board.

OK, please let us know of your findings.

JW

alessandro morniroli
Associate III

My bad,

I've just realized that on the board, on the MCU_RESET line there is a LM809M3-3.08 chip that is resetting my MCU @ 3.08V : )3

Thanks for coming back with the solution.

Please select your post as Best so that the thread can be marked as solved.

JW

eduardo_reis
Associate III

Is there any tutorial on PVD? I looked for one but I could not find. I am using a STM32H7. I enabled PVD on the .ioc file.

 

eduardo_reis_0-1730930655549.png

 

Then, on the initialization, I do this:

 

    PWR_PVDTypeDef pvd_config{PWR_PVDLEVEL_6, PWR_PVD_MODE_IT_FALLING};
    HAL_PWR_ConfigPVD(&pvd_config);
    HAL_PWR_EnablePVD();

 

And I defined this on main.c

 

void HAL_PWR_PVDCallback(){
  // some code here.
}

 

But, the interrupt callback is not being called. Is there someone that could help on this?