Skip to content

Instantly share code, notes, and snippets.

@diorcety
Last active February 9, 2024 08:59
Show Gist options
  • Select an option

  • Save diorcety/6f9e5d7e1a13c1c123d531d90e3d4716 to your computer and use it in GitHub Desktop.

Select an option

Save diorcety/6f9e5d7e1a13c1c123d531d90e3d4716 to your computer and use it in GitHub Desktop.
STM32 RDP without POR
/* From https://www.youtube.com/watch?v=f7vs0NwZPFo */
/*
* Warning -> if you use IWDG !
* EraseChip + POR + Flash -> will hang
* BlankChip + Flash -> will hang
* EraseChip + Flash -> may work
*
* In order to make it works you should do:
* (EraseChip + POR)/BlankChip + Flash + reload option bytes (stm32l4x option_load 0 with openocd)
* This will allow to use IWDG in any case after a Flash without another POR, and in this case, to change RDP without POR
*/
/**
* @brief Same as _HAL_PWR_EnterSTANDBYMode but in RAM
* @return void
*/
__RAM_FUNC void _HAL_PWR_EnterSTANDBYMode(void)
{
/* Set Stand-by mode */
MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STANDBY);
/* Set SLEEPDEEP bit of Cortex System Control Register */
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
/* This option is used to ensure that store operations are completed */
#if defined(__CC_ARM)
__force_stores();
#endif
/* Request Wait For Interrupt */
__WFI();
}
/**
* @brief Same behaviour that HAL_FLASH_OB_Launch but allow debugger attached
* @return void
*/
__RAM_FUNC void _flash_ob_launch(void)
{
__disable_irq();
/* Disable all DBG features */
CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
__HAL_DBGMCU_UNFREEZE_WWDG();
__HAL_DBGMCU_UNFREEZE_IWDG();
/* HAL_FLASH_OB_Launch is replaced by a standby */
/* To load new options into FLASH->OPTR from OB->RDP we need to wake from standby mode.
* Execution after exit from standby mode is same as a reset.
* For simplicity, use the IWDG to exit from standby.
*/
IWDG->KR = 0xCCCC; /* start */
IWDG->KR = 0x5555; /* enable access to PR and RLR regs */
IWDG->PR = IWDG_PR_PR_2; /* /64 prescaler for the dedicated 32kHz LSI clock = 512Hz */
IWDG->RLR = 256; /* count down from this value (256 is about 0.5secs at 512Hz) */
while (IWDG->SR) /* wait for setup to complete (slow clock domain) */
(void)0;
IWDG->KR = 0xAAAA; /* refresh (feed) the watchdog */
/* Clear all related wakeup flags */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
#if 0
HAL_PWR_EnterSTANDBYMode();
#else
_HAL_PWR_EnterSTANDBYMode();
#endif
// Should not reach here, rollback changes in case of...
/* Clear SLEEPDEEP bit of Cortex System Control Register */
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
/* Deselect Standby mode */
MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP0);
__enable_irq();
}
int main(void)
{
...
/* Program Option Bytes */
status |= HAL_FLASHEx_OBProgram(&OBStruct);
HAL_SuspendTick();
/* Launch Option Bytes Loading */
_flash_ob_launch();
...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment