2025-07-02 11:35 PM - last edited on 2025-07-03 12:15 AM by Andrew Neil
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.
2025-07-03 3:39 AM
Hello @Tom_18
Are you using the latest version of STM32Cube firmware L4?
2025-07-03 6:58 AM
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)