cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L1xx SPL 1.3.0: Bug - FLASH_OB_RDPConfig clobbers SPRMOD

Phil1
Associate II
Posted on December 17, 2014 at 15:49

In stm32l1xx_flash.c, there is a function

FLASH_Status

FLASH_OB_RDPConfig

(

uint8_t

OB_RDP

)

which is used to enable program memory read protection. Per RM0038 (

http://www.st.com/web/en/resource/technical/document/reference_manual/CD00240pdf

) the upper byte of option word 0x1FF80000 is used to store the SPRMOD bit:

Bits [31:25]: reserved must be set to 1

Bit 24: nSPRMOD

Bits [23:16]: nRDP

Bits [15:9]: reserved must be reset to 0

Bit 8: SPRMOD: sector protection mode selection

0: WRPx[i]=1 bit defines sector write protection

1: WRPx[i]=0 bit defines sector write and read (PCROP) protection.

See Section 3.7.4: PCROP for details.

Bits [7:0]: RDP: Read protection option byte (stored in FLASH_OBR[22:16])

The read protection is used to protect the software code stored in Flash memory.

0xAA: Level 0, no protection

0xCC: Level 2, chip protection (debug and boot in SRAM features disabled)

Others: Level 1, read protection of memories (debug features limited)

After executing the above function with OB_RDP_Level_1, the config word is set to 0x004400BB, which is invalid (SPRMOD clear with nSPRMOD also clear).

The function as presented in stm32l1xx_flash.c does not take into account the current setting of the SPRMOD bit, and will always set SPRMOD - this may not be what the user wants. To correct the function, change it to look like this:

/**
* @brief Enables or disables the read out protection.
* @note To correctly run this function, the FLASH_OB_Unlock() function
* must be called before.
* @param FLASH_ReadProtection_Level: specifies the read protection level. 
* This parameter can be:
* @arg OB_RDP_Level_0: No protection
* @arg OB_RDP_Level_1: Read protection of the memory
* @arg OB_RDP_Level_2: Chip protection
* 
* !!!Warning!!! When enabling OB_RDP_Level_2 it's no more possible to go back to level 1 or 0
* 
* @retval FLASH Status: The returned value can be: 
* FLASH_ERROR_PROGRAM, FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_OB_RDPConfig(uint8_t OB_RDP)
{
FLASH_Status status = FLASH_COMPLETE;
uint16_t tmp1 = 0;
uint32_t tmp2 = 0;
/* Check the parameters */
assert_param(IS_OB_RDP(OB_RDP));
status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
/* calculate the option byte to write */
tmp1 = (~((uint32_t)OB_RDP) & 0xFF) | ((~OB->RDP) & 0xFF00);
tmp2 = (uint32_t)(((uint32_t)((uint32_t)(tmp1) << 16)) | ((uint32_t)OB_RDP));
if
(status == FLASH_COMPLETE)
{ 
/* program read protection level */
OB->RDP = tmp2;
}
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
/* Return the Read protection operation Status */
return
status; 
}

Note that tmp1 is now a uint16_t, and the assignment to it has been changed to take the existing PCROP byte setting into account.
0 REPLIES 0