on 2022-11-29 08:23 AM
HAL_StatusTypeDef ClearnBootSel() { FLASH_OBProgramInitTypeDef OB; HAL_FLASHEx_OBGetConfig(&OB); /* OB.USERConfig returns the FLASH_OPTR register */ // Use it to check if OB programming is necessary if (OB.USERConfig & FLASH_OPTR_nBOOT_SEL) { HAL_FLASH_Unlock(); HAL_FLASH_OB_Unlock(); OB.OptionType = OPTIONBYTE_USER; OB.USERType = OB_USER_nBOOT_SEL; OB.USERConfig = OB_BOOT0_FROM_PIN; if ( HAL_FLASHEx_OBProgram(&OB) != HAL_OK ) { HAL_FLASH_OB_Lock(); HAL_FLASH_Lock(); return HAL_ERROR; } HAL_FLASH_OB_Launch(); /* We should not make it past the Launch, so lock * flash memory and return an error from function */ HAL_FLASH_OB_Lock(); HAL_FLASH_Lock(); return HAL_ERROR; } return HAL_OK; }
HAL_StatusTypeDef modifynRST() { FLASH_OBProgramInitTypeDef OB; HAL_FLASHEx_OBGetConfig(&OB); // check if if ( !(OB.USERConfig & FLASH_OPTR_nRST_STOP) || // nRST_STOP is cleared or (OB.USERConfig & FLASH_OPTR_nRST_STDBY) || // nRST_STDBY is set or !(OB.USERConfig & FLASH_OPTR_nRST_SHDW) ) // nRST_SHDW is cleared { HAL_FLASH_Unlock(); HAL_FLASH_OB_Unlock(); OB.OptionType = OPTIONBYTE_USER; OB.USERType = OB_USER_nRST_STOP | OB_USER_nRST_STDBY | OB_USER_nRST_SHDW; OB.USERConfig = OB_STOP_NORST | OB_STANDBY_RST | OB_SHUTDOWN_NORST; if ( HAL_FLASHEx_OBProgram(&OB) != HAL_OK ) { HAL_FLASH_OB_Lock(); HAL_FLASH_Lock(); return HAL_ERROR; } HAL_FLASH_OB_Launch(); /* We should not make it past the Launch, so lock * flash memory and return an error from function */ HAL_FLASH_OB_Lock(); HAL_FLASH_Lock(); return HAL_ERROR; } return HAL_OK; }
HAL_StatusTypeDef SetRDPLevel1() { FLASH_OBProgramInitTypeDef OB; HAL_FLASHEx_OBGetConfig(&OB); if (OB.RDPLevel != OB_RDP_LEVEL_1) { HAL_FLASH_Unlock(); HAL_FLASH_OB_Unlock(); OB.OptionType = OPTIONBYTE_RDP; OB.RDPLevel = OB_RDP_LEVEL_1; if ( HAL_FLASHEx_OBProgram(&OB) != HAL_OK ) { HAL_FLASH_OB_Lock(); HAL_FLASH_Lock(); return HAL_ERROR; } HAL_FLASH_OB_Launch(); /* We should not make it past the Launch, so lock * flash memory and return an error from function */ HAL_FLASH_OB_Lock(); HAL_FLASH_Lock(); return HAL_ERROR; } return HAL_OK; }
void getWriteProtections(uint8_t *ZoneA_Start, uint8_t *ZoneA_End, uint8_t *ZoneB_Start, uint8_t *ZoneB_End) { FLASH_OBProgramInitTypeDef OB; OB.WRPArea = OB_WRPAREA_ZONE_A; HAL_FLASHEx_OBGetConfig(&OB); *ZoneA_Start = OB.WRPStartOffset; *ZoneA_End = OB.WRPEndOffset; OB.WRPArea = OB_WRPAREA_ZONE_B; HAL_FLASHEx_OBGetConfig(&OB); *ZoneB_Start = OB.WRPStartOffset; *ZoneB_End = OB.WRPEndOffset; }
uint8_t a_beg, a_end, b_beg, b_end; getWriteProtections(&a_beg, &a_end, &b_beg, &b_end); if ( (a_beg > a_end) && (b_beg > b_end) ) { // No write protections active }
HAL_StatusTypeDef setWRP(uint8_t A_Start, uint8_t A_End, uint8_t B_Start, uint8_t B_End) { FLASH_OBProgramInitTypeDef OB; HAL_FLASH_Unlock(); HAL_FLASH_OB_Unlock(); OB.OptionType = OPTIONBYTE_WRP; OB.WRPArea = OB_WRPAREA_ZONE_A; OB.WRPStartOffset = A_Start; OB.WRPEndOffset = A_End; if ( HAL_FLASHEx_OBProgram(&OB) != HAL_OK ) { HAL_FLASH_OB_Lock(); HAL_FLASH_Lock(); return HAL_ERROR; } OB.WRPArea = OB_WRPAREA_ZONE_B; OB.WRPStartOffset = B_Start; OB.WRPEndOffset = B_End; if ( HAL_FLASHEx_OBProgram(&OB) != HAL_OK ) { HAL_FLASH_OB_Lock(); HAL_FLASH_Lock(); return HAL_ERROR; } HAL_FLASH_OB_Launch(); /* We should not make it past the Launch, so lock * flash memory and return an error from function */ HAL_FLASH_OB_Lock(); HAL_FLASH_Lock(); return HAL_ERROR; }
Some parts have WRP that is enabled or disabled on a sector-by-sector basis rather than being defined as a range between two sectors, such as with the H7 series. Here is an example of changing the WRP on the H743:
HAL_StatusTypeDef ChangeWRP(uint32_t bank_num, uint32_t state, uint32_t sectors) { FLASH_OBProgramInitTypeDef OB; OB.OptionType = OPTIONBYTE_WRP; OB.WRPState = state; OB.Banks = bank_num; OB.WRPSector = sectors; HAL_FLASH_Unlock(); HAL_FLASH_OB_Unlock(); if ( HAL_FLASHEx_OBProgram(&OB) != HAL_OK ) { HAL_FLASH_OB_Lock(); HAL_FLASH_Lock(); return HAL_ERROR; } HAL_FLASH_OB_Launch(); // Should not be reached HAL_FLASH_OB_Lock(); HAL_FLASH_Lock(); return HAL_ERROR; } ... ... ... // Example of enabling WRP on sectors 1, 3, 5 of Bank 1. uint32_t sectors = OB_WRP_SECTOR_1 | OB_WRP_SECTOR_3 | OB_WRP_SECTOR_5; ChangeWRP(FLASH_BANK_1, OB_WRPSTATE_ENABLE, sectors);
void getPCROP(uint32_t *ZoneA_Start, uint32_t *ZoneA_End, uint32_t *ZoneB_Start, uint32_t *ZoneB_End) { FLASH_OBProgramInitTypeDef OB; HAL_FLASHEx_OBGetConfig(&OB); *ZoneA_Start = OB.PCROP1AStartAddr; *ZoneA_End = OB.PCROP1AEndAddr; *ZoneB_Start = OB.PCROP1BStartAddr; *ZoneB_End = OB.PCROP1BEndAddr; }Just like with WRP, you can use the PCROP addresses to know if it is disabled. If the start address is greater than the end address for that zone, PCROP is disabled. Unlike the WRP API however, the PCROP values are given by the struct as the actual addresses, even though the PCROP option bytes themselves represent the address as an offset of lower granularity blocks.
HAL_StatusTypeDef setPCROP(uint32_t A_Start, uint32_t A_End, uint32_t B_Start, uint32_t B_End) { FLASH_OBProgramInitTypeDef OB; HAL_FLASH_Unlock(); HAL_FLASH_OB_Unlock(); OB.OptionType = OPTIONBYTE_PCROP; OB.PCROPConfig = OB_PCROP_ZONE_A | OB_PCROP_ZONE_B; OB.PCROP1AStartAddr = A_Start; OB.PCROP1AEndAddr = A_End; OB.PCROP1BStartAddr = B_Start; OB.PCROP1BEndAddr = B_End; if ( HAL_FLASHEx_OBProgram(&OB) != HAL_OK ) { HAL_FLASH_OB_Lock(); HAL_FLASH_Lock(); return HAL_ERROR; } HAL_FLASH_OB_Launch(); /* We should not make it past the Launch, so lock * flash memory and return an error from function */ HAL_FLASH_OB_Lock(); HAL_FLASH_Lock(); return HAL_ERROR; }
uint32_t ZoneA_beg = 0x8000473; uint32_t ZoneA_end = 0x8000891; uint32_t ZoneB_beg = 0x8000c35; uint32_t ZoneB_end = 0x8000f42; setPCROP(ZoneA_beg, ZoneA_end, ZoneB_beg, ZoneB_end);
// right shifted by 9 because 512 = 1 << 9 0x8000473 - 0x8000000 = 0x473 >> 9 = 2 0x8000891 - 0x8000000 = 0x891 >> 9 = 4 0x8000c35 - 0x8000000 = 0xc35 >> 9 = 6 0x8000f42 - 0x8000000 = 0xf42 >> 9 = 7
//512 bytes = 0x200 ZoneA_Start = 0x8000000 + (0x200 * 2) = 0x8000400 // Whole subsector is protected ZoneA_End = 0x8000000 + (0x200 * 4) = 0x8000800, end of that sector is 0x80009FF ZoneB_Start = 0x8000000 + (0x200 * 6) = 0x8000C00 // Whole subsector is protected ZoneB_End = 0x8000000 + (0x200 * 7) = 0x8000E00, end of that sector is 0x8000FFF Overall: Zone A = 0x8000400 to 0x80009FF (inclusive) Zone B = 0x8000C00 to 0x8000FFF (inclusive)
Hi,
I´m trying to program the 3 bits for booting options (STM32G0B1) with the HAL functions in the above manual. Unfortunately I can´t find the possible options like OB_USER_nBOOT_SEL. I searched the whole project, but coudn´t found any #define of this. Where are these constants defined?
Best regards,
Achim
Hi! Im trying to implement these method, but i have a lot of problems. Also on clean MCU(G0B1)
Hi @MCU Support TD ,
Can I use option bytes to store the data(eg: Serial number, values storage etc).is It possible if so please share the available resource link/ example for reference.
FYR:I am using STM32G491RE
Thanks