cancel
Showing results for 
Search instead for 
Did you mean: 

Issue Entering Stop Mode on CM4 of STM32H7

C-Coder
Associate III

I have a dual core application running on an STM32H7 where I would like:

 

  1. the CM7 to tell the CM4 to enter stop mode
  2. have the CM4 enter stop mode
  3. at a later time, have the CM7 wake the CM4 from said stop mode

In the CM4 code, I'm doing this:

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

The problem is that HAL_PWREx_EnterSTOPMode is immediately exiting. I use the HSEM library for synchronizing all communication between the CM7 and CM4. I thought that maybe I had a case where the CM7 was notifying the CM4 via the HSEM library when I didn't want it to, causing it to wake. So as a test, I added an infinite loop

while (1);

after notifying the CM4 so that the CM7 wouldn't execute anything else. I know that debugging can/will wake the core. To confirm that the CM4 was getting the notification and calling the above HAL_PWREx code, I turn on an LED, delay for 5 seconds, then make the calls. After the enter function returns, I blink the LED.

How can I determine what is waking the CM4? Is my understanding of the WFE and the HSEM library to perform the waking flat out wrong?

Thanks,

C-Coder

2 REPLIES 2
mƎALLEm
ST Employee

Hello;

Did you follow one of the examples provided in CubeHAL? 

From this example you have:

CM4:

int main(void)
{
 /*HW semaphore Clock enable*/
  __HAL_RCC_HSEM_CLK_ENABLE();
 
  /* Activate HSEM notification for Cortex-M4*/
  HAL_HSEM_ActivateNotification(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));
  
  /* 
    Domain D2 goes to STOP mode (Cortex-M4 in deep-sleep) waiting for Cortex-M7 to
    perform system initialization (system clock config, external memory configuration.. )   
  */
  HAL_PWREx_ClearPendingEvent();
  HAL_PWREx_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFE, PWR_D2_DOMAIN);

  /* Clear HSEM flag */
  __HAL_HSEM_CLEAR_FLAG(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));

 /* STM32H7xx HAL library initialization:
       - Systick timer is configured by default as source of time base, but user 
         can eventually implement his proper time base source (a general purpose 
         timer for example or other time source), keeping in mind that Time base 
         duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and 
         handled in milliseconds basis.
       - Set NVIC Group Priority to 4
       - Low Level Initialization
     */
  HAL_Init();
.
.

CM7:

int main(void)
{
  /* System Init, System clock, voltage scaling and L1-Cache configuration are done by CPU1 (Cortex-M7) 
     in the meantime Domain D2 is put in STOP mode(Cortex-M4 in deep-sleep)
  */
  
  /* Configure the MPU attributes */
  MPU_Config();

  /* Enable the CPU Cache */
  CPU_CACHE_Enable();
  
  
 /* STM32H7xx HAL library initialization:
       - Systick timer is configured by default as source of time base, but user 
         can eventually implement his proper time base source (a general purpose 
         timer for example or other time source), keeping in mind that Time base 
         duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and 
         handled in milliseconds basis.
       - Set NVIC Group Priority to 4
       - Low Level Initialization
     */
  HAL_Init();

  /* Configure the system clock to 400 MHz */
  SystemClock_Config();  
  
  /* When system initialization is finished, Cortex-M7 will release (wakeup) Cortex-M4  by means of 
     HSEM notification. Cortex-M4 release could be also ensured by any Domain D2 wakeup source (SEV,EXTI..).
  */
  
   /*HW semaphore Clock enable*/
  __HAL_RCC_HSEM_CLK_ENABLE();
  
    /*Take HSEM */
    HAL_HSEM_FastTake(HSEM_ID_0);   
   /*Release HSEM in order to notify the CPU2(CM4)*/     
    HAL_HSEM_Release(HSEM_ID_0,0);
.
.

 For CM4 HAL_Init() is called just after waking-up from the low power mode. Do you have the same thing in your code?

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.
C-Coder
Associate III

@mƎALLEm 

As I stated, I already have an app where the cores are using synchronized communication. So yes, at the beginning of the CM4 code, I have this:

  /*HW semaphore Clock enable*/
  __HAL_RCC_HSEM_CLK_ENABLE();
  /* Activate HSEM notification for Cortex-M4*/
  HAL_HSEM_ActivateNotification(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));
  /*
  Domain D2 goes to STOP mode (Cortex-M4 in deep-sleep) waiting for Cortex-M7 to
  perform system initialization (system clock config, external memory configuration.. )
  */
  HAL_PWREx_ClearPendingEvent();
  HAL_PWREx_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFE, PWR_D2_DOMAIN);
  /* Clear HSEM flag */
  __HAL_HSEM_CLEAR_FLAG(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));

  /* Grab SEM 1 so that when we release it, the CM7 will know a response is available. */
  while (HAL_HSEM_FastTake(HSEM_ID_1) != HAL_OK) { }
/* USER CODE END Boot_Mode_Sequence_1 */
  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

And near the beginning of the CM7 code I have this:

  /* MPU Configuration--------------------------------------------------------*/
  MPU_Config();

/* USER CODE BEGIN Boot_Mode_Sequence_1 */
#if !defined(CM7_SKIP_CM4_INIT)
  /* Wait until CPU2 boots and enters in stop mode or timeout*/
  while(__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) != RESET)
  {
    asm("nop");
  }
#endif /* CM7_SKIP_CM4_INIT */
/* USER CODE END Boot_Mode_Sequence_1 */
  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();
/* USER CODE BEGIN Boot_Mode_Sequence_2 */
#if !defined(CM7_SKIP_CM4_INIT)
  /* When system initialization is finished, Cortex-M7 will release (wakeup) Cortex-M4  by means of
     HSEM notification. Cortex-M4 release could be also ensured by any Domain D2 wakeup source (SEV,EXTI..).
  */

  /*HW semaphore Clock enable*/
  __HAL_RCC_HSEM_CLK_ENABLE();

  /*Take Our HSEM */
  HAL_HSEM_FastTake(HSEM_ID_0);

  /* Take the CM4 semaphore. */
  HAL_HSEM_FastTake(HSEM_ID_1);

  /*Release HSEM in order to notify the CPU2(CM4)*/
  HAL_HSEM_Release(HSEM_ID_0,0);

  /* wait until CPU2 wakes up from stop mode */
  while (__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) == RESET)
  {
    asm("nop");
  }
#endif /* CM7_SKIP_CM4_INIT */

and that works great. What I want/need is after things have been running for a while. Merely clearing the pending events and calling the enter method is not causing the CM4 to block. Thus, the presence or absence of a call to HAL_Init afterwards is irrelevant. Something is either waking up the CM4 or the enter call is failing (but of course there is no return value for that function).

Thanks,

C-Coder