cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103 option byte PGERR

Jeroen3
Senior

Posted on December 27, 2016 at 14:31

I'm trying to write the option bytes, but I get PGERR or Imprecise data bus error.

Here is some psuedo code that is what is happening. The HAL also does this, that's why I started from scratch using the programming manual. But to no avail.

... HSI is ON. Prefetch if off... two wait states

  _FLASH_CR_unlock();

  __disable_irq();

  FLASH->OPTKEYR = FLASH_KEY1;

  FLASH->OPTKEYR = FLASH_KEY2;

  FLASH->CR |= FLASH_CR_OPTPG;

  FLASH->SR |= FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR;

  *0x1FFFF804 = 0xAA;

  while(FLASH->SR & FLASH_SR_BSY);

  // Check for EOP bit and compare data.

  uint32_t SR = FLASH->SR;

... check and return flags

I've asked this before, in the old forum. However, I need this, so I'll ask again.

https://community.st.com/0D50X00009XkhNDSAZ

1 ACCEPTED SOLUTION

Accepted Solutions
Posted on December 27, 2016 at 16:53

I think I got it. You have to erase and program within a single unlock session.

Unlock FPEC

Unlock OPTWRE

Erase

Program

Lock 

OPTWRE

Lock FPEC

This is also why above sample code does not work, since it tries to unlock once again when programming after erasing. Causing the FPEC to become bricked until reset.

This might also be why the ST Link utility throws an error on the option bytes.

Edit: tried above, code works fine now.

Note: after erase, the complement values of the option bytes are disabled. (eg: entire region is 0xFF).

View solution in original post

2 REPLIES 2
Posted on December 27, 2016 at 16:02

The options data must be erased before it can be written, and the write must be 16-bit wide.

When doing changes you'd typically copy the original settings to a buffer, erase, and write back the new complete set.

The Flash must be unlocked (XL has two banks not sure if both need to be unlocked) prior to unlocking the Options

FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data)
{
 FLASH_Status status = FLASH_COMPLETE;
 /* Check the parameters */
 assert_param(IS_OB_DATA_ADDRESS(Address));
 status = FLASH_WaitForLastOperation(ProgramTimeout);
 if(status == FLASH_COMPLETE)
 {
 /* Authorize the small information block programming */
 FLASH->OPTKEYR = FLASH_KEY1;
 FLASH->OPTKEYR = FLASH_KEY2;
 /* Enables the Option Bytes Programming operation */
 FLASH->CR |= CR_OPTPG_Set;
 *(__IO uint16_t*)Address = Data;
 /* Wait for last operation to be completed */
 status = FLASH_WaitForLastOperation(ProgramTimeout);
 if(status != FLASH_TIMEOUT)
 {
 /* if the program operation is completed, disable the OPTPG Bit */
 FLASH->CR &= CR_OPTPG_Reset;
 }
 }
 /* Return the Option Byte Data Program Status */
 return status;
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
FLASH_Status FLASH_EraseOptionBytes(void)
{
 uint16_t rdptmp = RDP_Key;
 FLASH_Status status = FLASH_COMPLETE;
 /* Get the actual read protection Option Byte value */
 if(FLASH_GetReadOutProtectionStatus() != RESET)
 {
 rdptmp = 0x00;
 }
 /* Wait for last operation to be completed */
 status = FLASH_WaitForLastOperation(EraseTimeout);
 if(status == FLASH_COMPLETE)
 {
 /* Authorize the small information block programming */
 FLASH->OPTKEYR = FLASH_KEY1;
 FLASH->OPTKEYR = FLASH_KEY2;
 /* if the previous operation is completed, proceed to erase the option bytes */
 FLASH->CR |= CR_OPTER_Set;
 FLASH->CR |= CR_STRT_Set;
 /* Wait for last operation to be completed */
 status = FLASH_WaitForLastOperation(EraseTimeout);
 if(status == FLASH_COMPLETE)
 {
 /* if the erase operation is completed, disable the OPTER Bit */
 FLASH->CR &= CR_OPTER_Reset;
 /* Enable the Option Bytes Programming operation */
 FLASH->CR |= CR_OPTPG_Set;
 /* Restore the last read protection Option Byte value */
 OB->RDP = (uint16_t)rdptmp;
 /* Wait for last operation to be completed */
 status = FLASH_WaitForLastOperation(ProgramTimeout);
 if(status != FLASH_TIMEOUT)
 {
 /* if the program operation is completed, disable the OPTPG Bit */
 FLASH->CR &= CR_OPTPG_Reset;
 }
 }
 else
 {
 if (status != FLASH_TIMEOUT)
 {
 /* Disable the OPTPG Bit */
 FLASH->CR &= CR_OPTPG_Reset;
 }
 }
 }
 /* Return the erase status */
 return status;
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on December 27, 2016 at 16:53

I think I got it. You have to erase and program within a single unlock session.

Unlock FPEC

Unlock OPTWRE

Erase

Program

Lock 

OPTWRE

Lock FPEC

This is also why above sample code does not work, since it tries to unlock once again when programming after erasing. Causing the FPEC to become bricked until reset.

This might also be why the ST Link utility throws an error on the option bytes.

Edit: tried above, code works fine now.

Note: after erase, the complement values of the option bytes are disabled. (eg: entire region is 0xFF).