STM32CubeH7 icon indicating copy to clipboard operation
STM32CubeH7 copied to clipboard

H747/dual core CM7 continues execution after wakeup from standby mode with RTC.

Open iabdalkader opened this issue 4 years ago • 8 comments

I have a minimal application based on the STM32H747I-DISCO PWR_STANDBY_RTC example..

This is how it works:

  1. CM7 does basic initialization, and boots CM4.
  2. CM4 configures HSEM, go to STOP mode and wait for notification from CM7.
  3. CM7 configures HSEM and wakes up CM4.
  4. CM4 wakes up and puts D3 and then D2 in standby mode.
  5. CM7 configures RTC and enables EXTI_LINE19 for D1 and D2.
  6. CM7 puts D1 in standby mode.

The RTC wakeup timer fires on time, CM4 wakes up and rests as expected, but CM7 wakes up and instead of resetting it continues execution after HAL_PWREx_EnterSTANDBYMode(PWR_D1_DOMAIN);

Here's the CM4 main:

int main(void)
{  
    HAL_Init();
    blink_led(LED_GREEN);

    // HW semaphore Clock enable
    __HAL_RCC_HSEM_CLK_ENABLE();

    // Configure the NVIC HSEM notification interrupt for CM4
    HAL_NVIC_SetPriority(HSEM2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(HSEM2_IRQn);

    // Activate HSEM notification for Cortex-M4
    HAL_HSEM_ActivateNotification(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));

    HAL_PWREx_ClearPendingEvent();
    HAL_PWREx_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFE, PWR_D2_DOMAIN);

    HAL_PWREx_ClearPendingEvent();

    // Deactivate HSEM notification for Cortex-M4
    HAL_HSEM_DeactivateNotification(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));
    
    __HAL_RCC_HSEM_CLK_DISABLE();

    // Enter D3 domain to DStandby mode
    HAL_PWREx_EnterSTANDBYMode(PWR_D3_DOMAIN);

    // Enter D2 domain to DStandby mode
    HAL_PWREx_EnterSTANDBYMode(PWR_D2_DOMAIN);

    while (1) {
    }
}

CM7 code:

RTC_HandleTypeDef RTCHandle;

void RTC_WKUP_IRQHandler(void)
{
  HAL_RTCEx_WakeUpTimerIRQHandler(&RTCHandle);
}

void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc)
{
  RCC_OscInitTypeDef        RCC_OscInitStruct;
  RCC_PeriphCLKInitTypeDef  PeriphClkInitStruct;

  /* To enable access on RTC registers */
   HAL_PWR_EnableBkUpAccess();

  /*##-2- Configure LSE/LSI as RTC clock source ###############################*/
  RCC_OscInitStruct.OscillatorType =  RCC_OSCILLATORTYPE_LSE;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { 
      while (1) blink_led(100);
  }
  
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
  PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  if(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { 
      while (1) blink_led(100);
  }
  /* Configures the External Low Speed oscillator (LSE) drive capability */
  __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_HIGH); 
  
  /* Enable RTC Clock */ 
  __HAL_RCC_RTC_ENABLE(); 
 
  /*##-3- Configure the NVIC for RTC Alarm ###################################*/
  HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 0x0, 0);
  HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
}

static void RTC_Config(void)
{
  RTCHandle.Instance = RTC;
  RTCHandle.Init.HourFormat = RTC_HOURFORMAT_24;
  RTCHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
  RTCHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
  RTCHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
  RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  RTCHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  HAL_RTC_DeInit(&RTCHandle);
  if (HAL_RTC_Init(&RTCHandle) != HAL_OK) {
      while (1) blink_led(100);
  }
}

int main(void) 
{
    HAL_Init();
    blink_led(10);

    __HAL_RCC_HSEM_CLK_ENABLE();
    HAL_HSEM_FastTake(0);
    HAL_HSEM_Release(0, 0);
    __HAL_RCC_HSEM_CLK_DISABLE();
    
     SysTick->CTRL |= ~SysTick_CTRL_TICKINT_Msk;

    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
    // Wait for PWR_FLAG_VOSRDY
    while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {
    }

    PWR->WKUPCR |= PWR_WAKEUP_FLAG_ALL;

    RTC_Config();
    HAL_EXTI_D1_EventInputConfig(EXTI_LINE19, EXTI_MODE_IT | EXTI_MODE_EVT, ENABLE);
    HAL_EXTI_D2_EventInputConfig(EXTI_LINE19, EXTI_MODE_IT | EXTI_MODE_EVT, ENABLE);
    HAL_RTCEx_DeactivateWakeUpTimer(&RTCHandle);  
    HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 5000, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
    HAL_PWR_DisableBkUpAccess();

    __HAL_RCC_FLASH_C2_ALLOCATE();

    HAL_PWREx_EnterSTANDBYMode(PWR_D1_DOMAIN);

    SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
    while (1) blink_led(10000);  /// <-- CM7 wakes up after RTC timer and blinks LED.
}

Note: Changing the above slightly to make just the CM7 wake up, doesn't make any difference, it still wakes up and continues after the EnterSTANDBYMode call for example with the following:

HAL_HSEM_Release(0, 0);
HAL_Delay(100);  // <--- Add delay to make sure CM4 wakes up and goes to standby
.....
HAL_EXTI_D1_EventInputConfig(EXTI_LINE19, EXTI_MODE_IT, ENABLE);
HAL_EXTI_D2_EventInputConfig(EXTI_LINE19, EXTI_MODE_IT|EXTI_MODE_EVT, DISABLE); /// Disable RTC for CM4
.....
//__HAL_RCC_FLASH_C2_ALLOCATE(); // <-- CM4 doesn't need the flash; Not allocated to CM4

iabdalkader avatar Mar 21 '21 14:03 iabdalkader

Hi @iabdalkader,

Thank you for this report. Could the behavior you are observing be related to the Flash option bits, particularly NRST_STBY_D1? Would you mind checking using the Cube Programmer? Normally, the corresponding box should be checked. Please let me know as soon as you have checked this point.

With regards,

ALABSTM avatar Mar 23 '21 04:03 ALABSTM

Hi @ALABSTM I haven't changed any option bits, but I'll check anyway and get back to you as soon as I can. However, if I understand correctly, that option when cleared causes a reset on entry to standby mode, what I am seeing here is No reset on exit from standby mode. FWIW I see ~20mA current draw in standby mode, which is the same as stop mode, so I am thinking maybe it's possible that it's not actually going into standby and somehow just going to stop mode, which doesn't reset on exit. If this is true, what's could be keeping it from going into standby mode ?

iabdalkader avatar Mar 23 '21 04:03 iabdalkader

@ALABSTM Hi, sorry for the delay, I just checked and all the option bits seem to be set to their defaults.. NRST_STDY_D1 is set to 1 in FLASH->OPTSR_CUR which has this value 0xb86aaf0.

iabdalkader avatar Mar 24 '21 18:03 iabdalkader

@iabdalkader,

My turn to apologize for the delay. Any progress from your side? May I suggest you to have a look at this conversation (assuming you are using Cube IDE to debug your application)?

With regards,

ALABSTM avatar May 24 '21 08:05 ALABSTM

@ALABSTM Hi, no, no progress unfortunately, for now I just added a NVIC_SystemReset(); after EnterStandby so when the CM7 wakes up it resets... the power consumption is not ideal in Standby it's the same as Stop mode but this makes sure that CM7 won't be executing code that it shouldn't. Also I don't use Cube to debug I use GDB server from the command line, but either way not sure how to debug this I could try though if there's something you want me to check.

iabdalkader avatar May 31 '21 13:05 iabdalkader

Hi @iabdalkader,

I hope you are fine. Have you tried the latest STM32CubeH7 version (i.e., v1.10.0) published some time ago?

Actually, a fix has been implemented to properly configure RTC interrupts at EXTI level in case dual-core micros are used. Indeed, lines 2140 to 2147 have been added, as you can see on the code snippet below.

Please let me know whether this solves the problem.

With regards,

https://github.com/STMicroelectronics/STM32CubeH7/blob/b340b13929e36a3427b8d94e8b1006022f82273f/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rtc_ex.c#L2138-L2150

ALABSTM avatar Apr 05 '22 10:04 ALABSTM

Hi, I'm good and thanks for the update! We're using an older HAL I think, but I can patch it and test again. I don't have the hardware with me at the moment, but I will have it very soon, and will get back to you.

iabdalkader avatar Apr 05 '22 14:04 iabdalkader

Hello ,

I seem to have a similar problem.

I am using the latest HAL (1.0.10) in an STM32H757 Eval-board.

My workflow is the following:

  • CM4 boots up
  • Enables semaphore clock
  • activates the HSEM notification
  • CM4 goes to deep sleep (STOPMODE) and waits for CM7

CM7:

  • CM7 boots up
  • Waits for CM4 to go to sleep with a timeout
  • continues further execution on CM4 notification or timeout

The issue is CM4 never wakes back up. It seems like CM7 runs faster and timeouts, before CM4 can enter into deep sleep.

Can you share your opinion on this please.

rangakamesh avatar Oct 18 '22 20:10 rangakamesh

I actually fixed my problem, it was not entering a system standby mode as expected, but now it's working I see current draw ~2.4mA (still need to optimize a few other things), but it's good enough for now. @ALABSTM feel free to close this issue.

For the record, some (or all) of the following makes it work as expected:

  • If you enable any EXTIs you must mask them:
    // Clear any pending EXTIs.
    EXTI_D1->PR1 = 0x3fffff;

    // Mask all configurable EXTI lines.
    EXTI_D1->IMR1 &= ~(0xFFFFu); // 15 lines
  • Set voltage scaling level to 3 (i.e __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3)
  • Call HAL_Deinit() just before HAL_PWREx_EnterSTANDBYMode.

Other things that may or may not be needed:

  • Disable Debug MCU (DBGMCU->CR = 0)
  • Disable any clock enabled in sleep mode (search LPEN).

iabdalkader avatar Nov 15 '22 11:11 iabdalkader

Hi @iabdalkader,

Thank you for these details. As you suggested, I will close this issue.

With regards,

ALABSTM avatar Apr 04 '23 14:04 ALABSTM

Thank you for these details. As you suggested, I will close this issue.

You're welcome, furthermore when powered from VBAT I got it down to 200-300uA range.

iabdalkader avatar Apr 04 '23 14:04 iabdalkader