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

1 ACCEPTED SOLUTION

Accepted Solutions

You need to disable systick

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

View solution in original post

9 REPLIES 9
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

You need to disable systick

If you feel a post has answered your question, please click "Accept as Solution".
C-Coder
Associate III

@TDK Exactly what I was looking for, thank you very much. Any idea why calling

HAL_HSEM_Release(HSEM_ID_0, 0);

from the CM7 doesn't then wake up the CM4 (after it has entered stop mode)?

 

Thanks,

 

C-Coder

Hello,

Sorry but how the systick was enabled before calling HAL_Init() from CM4 side? the systick is enabled in HAL_Init() just after waking up from low power mode. That's why I asked for that in my previous answer. 

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 I think one or more words is missing from your response as it does not make sense. But you can see from my larger snippets of code above that the CM4 is enabling the SysTick via HAL_Init(). Now immediately where we want it to enter/exit Sleep Mode we have:

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

Unfortunately, when the CM7 calls:

HAL_HSEM_Release(HSEM_ID_0, 0);

the CM4 is not waking up.

Thanks,

C-Coder 

Here is the code of CM4:

  /*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();

HAL_Init() is called after HAL_PWREx_EnterSTOPMode() so when CM4 is in STOP mode, the system tick is not enabled yet. So regarding your statement: "The problem is that HAL_PWREx_EnterSTOPMode is immediately exiting." I don't see the system tick is the source of CM4 wake up. I'm suspecting something else ..

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

That code snippet is the very beginning of the CM4's main function. I'm not asking how to put the CM4 to sleep and wake it up at the beginning of the main function. I've already explained that that portion of the code is working just fine. The CM4 goes to sleep on initial start, the CM7 waits for it to go to sleep, then it initializes hardware, then it wakes up the CM4 and they continue running and communicating back and forth for some time (depends on use case, maybe it's 15 minutes until our inactivity timer expires and we want it to go to sleep, or maybe it is told by a user to go to sleep). Either way, the code you're referencing is NOT where the problem is. The problem is when we explicitly tell it to go to sleep. @TDK's suggestion of disabling SysTick before entering the STOP mode was the right call. Now it truly is going to sleep. I had seen the need for this step mentioned elsewhere and had forgotten to add it.

Now the problem is that the CM7 cannot seem to wake it via the HSEM library. So there must be something else missing as well.

C-Coder

Following this thread - did you get this working?  If yes, please post the details.  Thank you!