cancel
Showing results for 
Search instead for 
Did you mean: 

Changing RDP level from level 1 to level 0 on STM32C071

Shaf
Associate II

Post Edited by ST moderator to apply source code formatting


Hello,

To need to disable external read/write access to flash in stm32c071 i have changed the RDP from level 0(0xAA) to level 1(0xBB) and was successful in doing so. But when I try to change from level 1 to level 0 i am unable to change it. 

code to change from level 1  to level 0.

eFLASH_ErrorType_t FlashReadWriteEnable(void)

{

eFLASH_ErrorType_t err_code = e_SUCCESS;



// Check if flash is busy

err_code = CheckFlashBusy();

if(err_code == e_SUCCESS)

{

// Unlock flash

err_code = flashUnlock();

if(err_code == e_FLASH_UNLOCKED)

{

// user options unlock

err_code = flashOptUnlock();

if(err_code == e_FLASH_OPT_UNLOCKED)

{

FLASH->OPTR &= (~FLASH_OPTR_RDP_Msk);

FLASH->OPTR |= (0xAA << FLASH_OPTR_RDP_Pos);

FLASH->CR |= FLASH_CR_OPTSTRT;

// Check if flash is busy

err_code = CheckFlashBusy();

if(err_code == e_SUCCESS)

{

FLASH->CR |= FLASH_CR_OBL_LAUNCH;

}

}

}

}

return err_code;

}

 please help in resolving this. 


Regards,

Shafi

4 REPLIES 4
Onizuka09
ST Employee

Hello @Shaf , 

To perform RDP regression from Level 1 to Level 0, you need to use STM32CubeProgrammer.

At RDP Level 1, the flash is locked, so you cannot upload new code as you suggested.

To perform the RDP regression using STM32CubeProgrammer:

  • Connect to the board in Hot Plug mode.

RDPregression.png

  • Change the RDP to AA and apply the change. 
    RDP_regression_2.png

  • A full mass erase should have been performed. 

Best regards

Shaf
Associate II

Hello @Onizuka09,

Thanks for the quick reply!!

Yeah i am able to change rdp level 1 to level 0 to do using stm32programmer SW.  But i need to change using my code, so i have 2 routine in the same project

1. To change  from level 0 to 1.

2. To change from level 1 to 0.

if((FLASH->OPTR & FLASH_OPTR_RDP) == 0xBB)

{

WRITE_REG(GPIOA->BSRR, LL_GPIO_PIN_12);

FlashReadWriteEnable();



}

else

{

if((FLASH->OPTR & FLASH_OPTR_RDP) == 0xAA)

{

WRITE_REG(GPIOA->BSRR, LL_GPIO_PIN_12);

FlashReadWriteDisable();

}

}

Do I need to do any thing extra to apart from the above?
Regards,

Shafi

Onizuka09
ST Employee

Hello @Shaf ,

I could not reproduce your issue. You can find the full example below.

For the RDP configuration:

  1. Wait until the flash is not busy
  2. Unlock the flash
  3. Unlock the option bytes
  4. Save the current content of the OPTR register in a temporary variable
  5. Make the necessary changes to that variable by setting the RDP level
  6. Write the temporary variable back to the OPTR register and start programming
  7. Launch the option byte reload operation, which will cause a system reset
  8. Lock the flash and the option byte registers

In the example below, I used the C0 BSP to control the LED and the user button, but you can use HAL for that instead.

The example waits for the user button press and, depending on the current RDP level, either enables or disables flash access.

For each RDP level state, you need to power cycle the board by unplugging and reconnecting the power supply, such as the USB cable.

Also, you cannot use the debugger session after RDP Level 1 is set. You need to close the debug session and power cycle the board.


 

typedef enum {
	e_SUCCESS = 0, e_ERROR, e_FLASH_UNLOCKED , e_FLASH_OPT_UNLOCKED
} eFLASH_ErrorType_t;
eFLASH_ErrorType_t CheckFlashBusy() {

	while (FLASH->SR & FLASH_SR_BSY1) {
	}

	return e_SUCCESS;
}
eFLASH_ErrorType_t flashUnlock(){
    if (FLASH->CR & FLASH_CR_LOCK)
    {
        FLASH->KEYR = FLASH_KEY1;
        FLASH->KEYR= FLASH_KEY2;
        return e_FLASH_UNLOCKED ;
    }
    return e_ERROR;
}
eFLASH_ErrorType_t flashOptUnlock() {
	if (FLASH->CR & FLASH_CR_OPTLOCK) {
		FLASH->OPTKEYR = FLASH_OPTKEY1;
		FLASH->OPTKEYR = FLASH_OPTKEY2;
		return e_FLASH_OPT_UNLOCKED;
	}
	return e_ERROR;
}

eFLASH_ErrorType_t FlashReadWriteEnable(void)

{
	eFLASH_ErrorType_t err_code = e_SUCCESS;
	err_code = CheckFlashBusy();
	if (err_code == e_SUCCESS) {
		err_code = flashUnlock();
		if (err_code == e_FLASH_UNLOCKED) {
			err_code = flashOptUnlock();
			if (err_code == e_FLASH_OPT_UNLOCKED) {
				uint32_t optr = FLASH->OPTR;
				optr &= ~FLASH_OPTR_RDP_Msk;
				optr |= (0xBB << FLASH_OPTR_RDP_Pos);
				FLASH->OPTR = optr;
				FLASH->CR |= FLASH_CR_OPTSTRT;

				err_code = CheckFlashBusy();
				if (err_code == e_SUCCESS) {
					FLASH->CR |= FLASH_CR_OBL_LAUNCH;
					// lock the flash
					FLASH->CR |= FLASH_CR_LOCK;
					FLASH->CR |= FLASH_CR_OPTLOCK ;
					// This will perform a system reset
					return e_ERROR;
				}
			}
		}
	}
	return e_SUCCESS;
}

eFLASH_ErrorType_t FlashReadWriteDisable(void)
{
	eFLASH_ErrorType_t err_code = e_SUCCESS;
	err_code = CheckFlashBusy();
	if (err_code == e_SUCCESS) {
		err_code = flashUnlock();
		if (err_code == e_FLASH_UNLOCKED) {
			err_code = flashOptUnlock();
			if (err_code == e_FLASH_OPT_UNLOCKED) {
				uint32_t optr = FLASH->OPTR;
				optr &= ~FLASH_OPTR_RDP_Msk;
				optr |= ( 0xAA << FLASH_OPTR_RDP_Pos);
				FLASH->OPTR = optr;
				FLASH->CR |= FLASH_CR_OPTSTRT;
				err_code = CheckFlashBusy();
				if (err_code == e_SUCCESS) {
					// This will perform a system reset
					FLASH->CR |= FLASH_CR_OBL_LAUNCH;
					// lock the flash
					FLASH->CR |= FLASH_CR_LOCK;
					FLASH->CR |= FLASH_CR_OPTLOCK ;
				}
			}
		}
	}
	return err_code;
}


// main 
int main(void) {

	/* USER CODE BEGIN 1 */

	/* USER CODE END 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 SysInit */

	/* USER CODE END SysInit */

	/* Initialize all configured peripherals */
	MX_GPIO_Init();
	MX_USART2_UART_Init();
	/* USER CODE BEGIN 2 */

	/* USER CODE END 2 */

	/* Initialize leds */
	BSP_LED_Init(LED_GREEN);
	BSP_LED_Init(LED_BLUE);

	/* Initialize USER push-button, will be used to trigger an interrupt each time it's pressed.*/
	BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);

	/* Infinite loop */

	/* USER CODE BEGIN WHILE */
	while (1) {
		uint32_t state = 0;
		if ((FLASH->OPTR & FLASH_OPTR_RDP) == 0xBB) {
			BSP_LED_On(LED_BLUE);
			state = 1;
		} else if ((FLASH->OPTR & FLASH_OPTR_RDP) == 0xAA) {
			BSP_LED_On(LED_GREEN);
			state = 2;
		}
		if (BSP_PB_GetState(BUTTON_USER) == 0) {
			if (state == 1) {
				FlashReadWriteDisable();
			} else if (state == 2) {
				FlashReadWriteEnable();
			}
		}
		/* USER CODE END WHILE */

		/* USER CODE BEGIN 3 */
	}
	/* USER CODE END 3 */
}


 Best regards,

Hello @Onizuka09,

I am able to change RDP from Level 0 to level 1 and vice versa on STM32C071 dev kit. But need to figure out why i am i not able to do it my custom board. Will update you after testing the same code on my custom board.  

Regards,

Shafi