2016-12-27 05:31 AM
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
Solved! Go to Solution.
2016-12-27 08:53 AM
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).
2016-12-27 07:02 AM
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;
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2016-12-27 08:53 AM
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).