cancel
Showing results for 
Search instead for 
Did you mean: 

Global Interrupt Disabling in LPTIM_Disable()

Tom_18
Visitor

Could you please explain why global interrupts are disabled (using __disable_irq()) at the beginning of the LPTIM_Disable() function, and re-enabled at the end?

Does this relate to ensuring atomicity during the timer's register save/restore process, preventing potential race conditions during clock source reconfiguration, or avoiding unintended interrupt triggers during the reset sequence?"

void LPTIM_Disable(LPTIM_HandleTypeDef *hlptim)
{
uint32_t tmpclksource = 0;
uint32_t tmpIER;
uint32_t tmpCFGR;
uint32_t tmpCMP;
uint32_t tmpARR;
uint32_t tmpOR;
#if defined(LPTIM_RCR_REP)
uint32_t tmpRCR;
#endif

__disable_irq();

/*********** Save LPTIM Config ***********/
/* Save LPTIM source clock */
switch ((uint32_t)hlptim->Instance)
{
case LPTIM1_BASE:
tmpclksource = __HAL_RCC_GET_LPTIM1_SOURCE();
break;
#if defined(LPTIM2)
case LPTIM2_BASE:
tmpclksource = __HAL_RCC_GET_LPTIM2_SOURCE();
break;
#endif /* LPTIM2 */
default:
break;
}

/* Save LPTIM configuration registers */
tmpIER = hlptim->Instance->IER;
tmpCFGR = hlptim->Instance->CFGR;
tmpCMP = hlptim->Instance->CMP;
tmpARR = hlptim->Instance->ARR;
tmpOR = hlptim->Instance->OR;
#if defined(LPTIM_RCR_REP)
tmpRCR = hlptim->Instance->RCR;
#endif

/*********** Reset LPTIM ***********/
switch ((uint32_t)hlptim->Instance)
{
case LPTIM1_BASE:
__HAL_RCC_LPTIM1_FORCE_RESET();
__HAL_RCC_LPTIM1_RELEASE_RESET();
break;
#if defined(LPTIM2)
case LPTIM2_BASE:
__HAL_RCC_LPTIM2_FORCE_RESET();
__HAL_RCC_LPTIM2_RELEASE_RESET();
break;
#endif /* LPTIM2 */
default:
break;
}

/*********** Restore LPTIM Config ***********/
#if defined(LPTIM_RCR_REP)
if ((tmpCMP != 0UL) || (tmpARR != 0UL) || (tmpRCR != 0UL))
#else
if ((tmpCMP != 0UL) || (tmpARR != 0UL))
#endif
{
/* Force LPTIM source kernel clock from APB */
switch ((uint32_t)hlptim->Instance)
{
case LPTIM1_BASE:
__HAL_RCC_LPTIM1_CONFIG(RCC_LPTIM1CLKSOURCE_PCLK1);
break;
#if defined(LPTIM2)
case LPTIM2_BASE:
__HAL_RCC_LPTIM2_CONFIG(RCC_LPTIM2CLKSOURCE_PCLK1);
break;
#endif /* LPTIM2 */
default:
break;
}

if (tmpCMP != 0UL)
{
/* Restore CMP register (LPTIM should be enabled first) */
hlptim->Instance->CR |= LPTIM_CR_ENABLE;
hlptim->Instance->CMP = tmpCMP;

/* Wait for the completion of the write operation to the LPTIM_CMP register */
if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT)
{
hlptim->State = HAL_LPTIM_STATE_TIMEOUT;
}
__HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK);
}

if (tmpARR != 0UL)
{
/* Restore ARR register (LPTIM should be enabled first) */
hlptim->Instance->CR |= LPTIM_CR_ENABLE;
hlptim->Instance->ARR = tmpARR;

/* Wait for the completion of the write operation to the LPTIM_ARR register */
if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT)
{
hlptim->State = HAL_LPTIM_STATE_TIMEOUT;
}

__HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
}
#if defined(LPTIM_RCR_REP)

if (tmpRCR != 0UL)
{
/* Restore RCR register (LPTIM should be enabled first) */
hlptim->Instance->CR |= LPTIM_CR_ENABLE;
hlptim->Instance->RCR = tmpRCR;

/* Wait for the completion of the write operation to the LPTIM_RCR register */
if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_REPOK) == HAL_TIMEOUT)
{
hlptim->State = HAL_LPTIM_STATE_TIMEOUT;
}
__HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_REPOK);
}
#endif

/* Restore LPTIM source kernel clock */
switch ((uint32_t)hlptim->Instance)
{
case LPTIM1_BASE:
__HAL_RCC_LPTIM1_CONFIG(tmpclksource);
break;
#if defined(LPTIM2)
case LPTIM2_BASE:
__HAL_RCC_LPTIM2_CONFIG(tmpclksource);
break;
#endif /* LPTIM2 */
default:
break;
}
}

/* Restore configuration registers (LPTIM should be disabled first) */
hlptim->Instance->CR &= ~(LPTIM_CR_ENABLE);
hlptim->Instance->IER = tmpIER;
hlptim->Instance->CFGR = tmpCFGR;
hlptim->Instance->OR = tmpOR;

__enable_irq();
}

Edited to apply source code formatting - please see How to insert source code for future reference.

2 REPLIES 2
Saket_Om
ST Employee

Hello @Tom_18 

Are you using the latest version of STM32Cube firmware L4?

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.
Saket_Om
TDK
Super User

As it states in the code, see ES0335 for the limitation this code is working around.

/**
  * @brief  Disable LPTIM HW instance.
  * @PAram  hlptim pointer to a LPTIM_HandleTypeDef structure that contains
  *                the configuration information for LPTIM module.
  * @note   The following sequence is required to solve LPTIM disable HW limitation.
  *         Please check Errata Sheet ES0335 for more details under "MCU may remain
  *         stuck in LPTIM interrupt when entering Stop mode" section.
  * @retval None
  */
void LPTIM_Disable(LPTIM_HandleTypeDef *hlptim)

 

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