2014-12-17 06:49 AM
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.