cancel
Showing results for 
Search instead for 
Did you mean: 

STM32WB55 MAC 802.15.4 Standby Mode Wake-Up Issue After MX_APPE_Init

YBAYR.1
Associate III

I am working on an example project: MAC 802 (\STM32Cube\Repository\STM32Cube_FW_WB_V1.21.0\Projects\P-NUCLEO-WB55.Nucleo\Applications\Mac_802_15_4\Mac_802_15_4_Node).
I have added standby mode to this code, but I am unable to wake it up.
After entering standby using RTC, the system does not wake up after MX_APPE_Init();.
My code is as follows:

int main(void)
{
  /* Initialize the HAL */
  HAL_Init();

  Check_Wakeup_Source();

  ALGORTM.WakeUp_From_stopM = true;

  /* Config code for STM32_WPAN (HSE Tuning must be done before system clock configuration) */
  MX_APPE_Config();

  ALGORTM.WakeUp_From_stopM = true;


  Load_Values_From_FLASH();

  /*Configure the system clock */
  SystemClock_Config();

  /* Configure the peripherals common clocks */
  PeriphCommonClock_Config();

  /* IPCC initialisation */
  MX_IPCC_Init();

//  LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);





  MX_GPIO_Init();

  MX_RTC_Init();


  MX_I2C3_Init();
  MX_TIM1_Init();
  MX_TIM2_Init();
  MX_TIM17_Init();
//  MX_ADC1_Init();



  /* Configure RTC to use WUT */
   Configure_RTC();
   /* Note: On STM32WB, both CPU1 and CPU2 must be in standby mode to set the entire system in standby mode */
   if ((LL_PWR_IsActiveFlag_C1SB() != 0)
       && (LL_PWR_IsActiveFlag_C2SB() != 0)
      )
   {
     /* ##### Run after standby mode ##### */
     /* Clear Standby flag */
     LL_PWR_ClearFlag_C1STOP_C1STB();
     LL_PWR_ClearFlag_C2STOP_C2STB();

     /* Reset RTC Internal Wake up flag */
     LL_RTC_ClearFlag_WUT(RTC);

     /* Slow Toggle LED */
     //LED_Blinking(LED_BLINK_SLOW);
   }
   else
   {

     /* ##### Run after normal reset ##### */
     /* Fast Toggle LED in waiting for user-button press */
    // WaitForUserButtonPress();

     /* Enable wake-up timer and enter in standby mode */
   }





  ALGORTM.WakeUp_From_stopM = true;
  sleep_UUID_sameconn = false;



  HAL_GPIO_WritePin(Enable_DS_GPIO_Port,Enable_DS_Pin, GPIO_PIN_SET);


  HAL_GPIO_WritePin(EN_125_GPIO_Port, EN_125_Pin, GPIO_PIN_SET);
  HAL_GPIO_WritePin(PS_125_GPIO_Port,PS_125_Pin, GPIO_PIN_SET);



	SET_CONFIG_PAGE(CF_PAGE_1+TXDIS); 									//0x51
	HAL_Delay(37);
	SET_CONFIG_PAGE(CF_PAGE_1+TXDIS); 									//0x51
	HAL_Delay(41);
	trycount = 0;
	successcountuid = 0;
	successcountslct = 0;
	successchallengecnt = 0;
	successtagreadcnt = 0;
	i=7;
	for(i=0; i<64; i++)
	memset(&saverecord[i],0,4);
	i=0;
	UTTS_Routine(i);                                               //       init


  //-------------------------------------------------    Sensor ultra low power init -------------------------------//
  Ism330_Init_ULP();

	HAL_GPIO_TogglePin(LED5_GPIO_Port, LED5_Pin);

HAL_Delay(200);

		//Enable_Wakeup_Pins();

		//Enter_ULP();



	HAL_GPIO_WritePin(Enable_DS_GPIO_Port,Enable_DS_Pin, GPIO_PIN_SET);


  if (HAL_TIM_Base_Start_IT(&htim17) != HAL_OK)
  {
      Error_Handler();
  }

	 int result = 0;

for (int attempt = 0; attempt < 2; ++attempt)
{

	  HAL_Delay(150);
	 result = VerifyCertifica();

	if (result == 1) {

		HAL_GPIO_TogglePin(LED7_GPIO_Port, LED7_Pin);


		Flash_Erase_Pages(FLASH_ROM_BAT_ID_ADDRESS, 2);


		uint8_t ROM_BAT_ID[4];
		memcpy(ROM_BAT_ID, romID, sizeof(ROM_BAT_ID));
		uint32_t ROM_BAT_ID_flash;
		memcpy(&ROM_BAT_ID_flash, ROM_BAT_ID, sizeof(ROM_BAT_ID_flash));
		Flash_Write_Data(FLASH_ROM_BAT_ID_ADDRESS, &ROM_BAT_ID_flash, 1);
		ReadAndTransmitFromFlash(FLASH_ROM_BAT_ID_ADDRESS);

		break;
	}

}



  MX_ADC1_Init();
  HAL_Delay(10);
  battery_typ = batType();
  Device_info.bat_level =  Read_Battery_Level(battery_typ);

  if (HAL_TIM_Base_Stop_IT(&htim17) != HAL_OK)
  {
      Error_Handler();
  }



	HW_IPCC_Disable();
	LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
	  Configure_RTC();

	  RTC_WakeUpTimer_Set_LL(0x2524);

	  Enable_Wakeup_Pins();

	  EnterStandbyMode();


  /* Application init */
  MX_APPE_Init();


	ALGORTM.TAG_Read_0 = true;
	ALGORTM.TTO_config = false;





  /* Main Loop  */
  while (1)
  {
}
void Configure_RTC(void)
{
  /*##-1- Enables the PWR Clock and Enables access to the backup domain #######*/
  /* To change the source clock of the RTC feature (LSE, LSI), you have to:
     - Enable the power clock
     - Enable write access to configure the RTC clock source (to be done once after reset).
     - Reset the Back up Domain
     - Configure the needed RTC clock source */

  LL_PWR_EnableBkUpAccess();

  /*##-2- Configure LSE/LSI as RTC clock source ###############################*/
#ifdef RTC_CLOCK_SOURCE_LSE
  /* Enable LSE only if disabled.*/
  if (LL_RCC_LSE_IsReady() == 0)
  {
    LL_RCC_ForceBackupDomainReset();
    LL_RCC_ReleaseBackupDomainReset();
    LL_RCC_LSE_Enable();
#if (USE_TIMEOUT == 1)
    Timeout = LSE_TIMEOUT_VALUE;
#endif /* USE_TIMEOUT */
    while (LL_RCC_LSE_IsReady() != 1)
    {
#if (USE_TIMEOUT == 1)
      if (LL_SYSTICK_IsActiveCounterFlag())
      {
        Timeout --;
      }
      if (Timeout == 0)
      {
        /* LSE activation error */
        LED_Blinking(LED_BLINK_ERROR);
      }
#endif /* USE_TIMEOUT */
    }
    LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);

    /*##-3- Enable RTC peripheral Clocks #######################################*/
    /* Enable RTC Clock */
    LL_RCC_EnableRTC();
    LL_APB2_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
  }
#elif defined(RTC_CLOCK_SOURCE_LSI)
  if (LL_RCC_LSI1_IsReady() == 0)
  {
    LL_RCC_ForceBackupDomainReset();
    LL_RCC_ReleaseBackupDomainReset();
    LL_RCC_LSI1_Enable();
#if (USE_TIMEOUT == 1)
    Timeout = LSI_TIMEOUT_VALUE;
#endif /* USE_TIMEOUT */
    while (LL_RCC_LSI1_IsReady() != 1)
    {
#if (USE_TIMEOUT == 1)
      if (LL_SYSTICK_IsActiveCounterFlag())
      {
        Timeout --;
      }
      if (Timeout == 0)
      {
        /* LSI1 activation error */
        LED_Blinking(LED_BLINK_ERROR);
      }
#endif /* USE_TIMEOUT */
    }
    LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSI);

    /*##-3- Enable RTC peripheral Clocks #######################################*/
    /* Enable RTC Clock */
    LL_RCC_EnableRTC();
    LL_APB2_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
  }

#else
//#error "configure clock for RTC"
#endif

  /*##-4- Configure RTC ######################################################*/
  /* Disable RTC registers write protection */
  LL_RTC_DisableWriteProtection(RTC);

  /* Set prescaler according to source clock */
  LL_RTC_SetAsynchPrescaler(RTC, RTC_ASYNCH_PREDIV);
  LL_RTC_SetSynchPrescaler(RTC, RTC_SYNCH_PREDIV);

  /* Disable wake up timer to modify it */
  LL_RTC_WAKEUP_Disable(RTC);

  /* Wait until it is allow to modify wake up reload value */
#if (USE_TIMEOUT == 1)
  Timeout = RTC_TIMEOUT_VALUE;
#endif /* USE_TIMEOUT */

  while (LL_RTC_IsActiveFlag_WUTW(RTC) != 1)
  {
#if (USE_TIMEOUT == 1)
    if (LL_SYSTICK_IsActiveCounterFlag())
    {
      Timeout --;
    }
    if (Timeout == 0)
    {
      /* LSI activation error */
      LED_Blinking(LED_BLINK_ERROR);
    }
#endif /* USE_TIMEOUT */
  }

  /* Setting the Wakeup time to RTC_WUT_TIME s
       If LL_RTC_WAKEUPCLOCK_CKSPRE is selected, the frequency is 1Hz,
       this allows to get a wakeup time equal to RTC_WUT_TIME s
       if the counter is RTC_WUT_TIME */
  LL_RTC_WAKEUP_SetAutoReload(RTC, RTC_WUT_TIME);
  LL_RTC_WAKEUP_SetClock(RTC, LL_RTC_WAKEUPCLOCK_CKSPRE);

  /* Enable RTC registers write protection */
  LL_RTC_EnableWriteProtection(RTC);

}
/**
  * @brief  Function to configure and enter in STANDBY Mode.
  *   None
  * @retval None
  */
void EnterStandbyMode(void)
{
  /* ######## ENABLE WUT #################################################*/
  /* Disable RTC registers write protection */
  LL_RTC_DisableWriteProtection(RTC);

  /* Enable wake up counter and wake up interrupt */
  /* Note: Periodic wakeup interrupt should be enabled to exit the device
     from low-power modes.*/
  LL_RTC_EnableIT_WUT(RTC);
  LL_RTC_WAKEUP_Enable(RTC);

  /* Enable RTC registers write protection */
  LL_RTC_EnableWriteProtection(RTC);

  /* ######## ENTER IN STANDBY MODE ######################################*/
  /** Request to enter STANDBY mode
    * Following procedure describe in STM32WBxx Reference Manual
    * See PWR part, section Low-power modes, Standby mode
    */
  /* Reset Internal Wake up flag */
  LL_RTC_ClearFlag_WUT(RTC);

  /* Check that PWR Internal Wake-up is enabled */
  if (LL_PWR_IsEnabledInternWU() == 0)
  {
    /* Need to enable the Internal Wake-up line */
    LL_PWR_EnableInternWU();
  }

  /* Set Standby mode */
  LL_PWR_SetPowerMode(LL_PWR_MODE_STANDBY);

  /* Set Standby mode of CPU2 */
  /* Note: On STM32WB, both CPU1 and CPU2 must be in Standby mode to set the entire system in Standby mode */
  LL_C2_PWR_SetPowerMode(LL_PWR_MODE_STANDBY);

  /* Set SLEEPDEEP bit of Cortex System Control Register */
  LL_LPM_EnableDeepSleep();

  /* This option is used to ensure that store operations are completed */
#if defined ( __CC_ARM)
  __force_stores();
#endif

  /* Request Wait For Interrupt */
  __WFI();
}

void Enable_Wakeup_Pins(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // Wakeup pinleri için GPIO clock'larını aktif et
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();

    // 1. PA0 ve PC5 pinlerini default INPUT (pull yok) moduna al
    // PA0 = WakeUp1
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // PC5 = WakeUp5
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    // 2. Backup domain erişimini aç (gerekiyorsa)
    LL_PWR_EnableBkUpAccess();

    // 3. Önce eski konfigürasyonları sıfırla
  //  LL_PWR_DisableWakeUpPin(LL_PWR_WAKEUP_PIN1);
    LL_PWR_DisableWakeUpPin(LL_PWR_WAKEUP_PIN5);
    LL_PWR_ClearFlag_WU();

    // 4. WakeUp Pin 1 ve 5'i aktif et (default rising edge ile)
 //   LL_PWR_EnableWakeUpPin(LL_PWR_WAKEUP_PIN1);  // PA0
    LL_PWR_EnableWakeUpPin(LL_PWR_WAKEUP_PIN5);  // PC5
}


void RTC_WakeUpTimer_Set_LL(uint32_t wakeup_counter)
{
    /* RTC write protection disable */
    LL_RTC_DisableWriteProtection(RTC);

    /* WakeUp timer disable before config */
    LL_RTC_WAKEUP_Disable(RTC);

    /* Wait for WUTWF flag (WakeUp Timer Write Flag) */
    while (!LL_RTC_IsActiveFlag_WUTW(RTC));

    /* Set wakeup auto-reload value */
    LL_RTC_WAKEUP_SetAutoReload(RTC, wakeup_counter);

    /* Set wakeup clock divider (RTC/16) */
    LL_RTC_WAKEUP_SetClock(RTC, LL_RTC_WAKEUPCLOCK_DIV_16);

    /* Clear WUTF flag */
    LL_RTC_ClearFlag_WUT(RTC);

    /* Enable wakeup interrupt */
    LL_RTC_EnableIT_WUT(RTC);

    /* Enable EXTI Line 22 for RTC WakeUp */
    LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_22);
    LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_22);

    /* Enable RTC WakeUp */
    LL_RTC_WAKEUP_Enable(RTC);

    /* RTC write protection enable */
    LL_RTC_EnableWriteProtection(RTC);

    /* Enable NVIC interrupt for RTC WakeUp */
    NVIC_SetPriority(RTC_WKUP_IRQn, 0);
    NVIC_EnableIRQ(RTC_WKUP_IRQn);
}
1 REPLY 1
FilipKremen
ST Employee

Hello,

since the example project includes low power manager and sequencer, I recommend using it for managing LP modes.

Once the sequencer has no task to run, it goes automatically to selected low power mode. For standby mode, all the RF activity must be stopped. I'm attaching P2P_server project with standby mode with several wakeup options, please read more information in README file. Also, don't hesitate to ask if you need further help.

Best regards,

Filip Kremen