; -------------------------------------------------------------------------------- ; @Title: Option bytes Programming script for STM32H7 drivatives ; ; @Description: ; Script Parameters: ; ; DO ~~/demo/arm/flash/stm32h7-optionbyte ; [BOR_LEV=0..3] ; [IWDG1_SW=0|1] [NRST_STOP_D1=0|1] [NRST_STDBY_D1=0|1] ; [RDP=0|1] [IWDG_FZ_STOP=0|1] [IWDG_FZ_SDBY=0|1] [IWDG_STDBY=0|1] ; [ST_RAM_SIZE=0|1] [SECURITY=0|1] [IO_HSLV=0|1] [SWAP_BANK_OPT=0|1] ; [BOOT_ADD0= ] [BOOT_ADD1= ] [PROT_AREA_END1=] ; [DMEP1=0|1] [PROT_AREA_START1=] ; [PROT_AREA_END2=] [DMEP2=0|1] ; [PROT_AREA_START2=] [SEC_AREA_END1=] [DMES1=0|1] ; [SEC_AREA_START1=] [SEC_AREA_END2=] [DMES2=0|1] ; [SEC_AREA_START2=] [WRPSn1=] [WRPSn2=] ; [RESETDEVICE] ; ; Program the STM32H7 option bytes according to the following parameters: ; ; BOR_LEV=0..3: Brownout level option configuration bit ; 0: BOR Level 0: Reset level is set to 1.6 V ; 1: BOR Level 1: Reset is set to 2.1 V ; 2: BOR Level 2: Reset is set to 2.4 V ; 3: BOR Level 3: Reset level is set to 2.7 V ; ; IWDG1_SW=0|1 IWDG1 control mode option configuration bit ; 0: IWDG1 watchdog is controller by hardware ; 1: IWDG1 watchdog is controlled by software ; ; NRST_STOP_D1=0|1 D1 domain DStop entry reset option status bit ; 0: A reset is generated when entering DStop mode on D1 domain ; 1: No reset generated ; ; NRST_STDBY_D1=0|1 D1 domain DStandby entry reset option status bit ; 0: A reset is generated when entering DStandby mode on D1 domain ; 1: No reset generated ; ; RDP=0|1 is programming read protection option byte ; 0: Disables flash read out protection (Level 0 : 0xAA) ; 1: Enables flash read out protection (Level 1 : 0x00) ; the script doesn't support programming Level 2, because with it no ; further debugging would be possible! ; ; IWDG_FZ_STOP=0|1 is programming IWDG_FZ_STOP bit of user option byte ; 0: Independent watchdog frozen in system Stop mode ; 1: Independent watchdog keep running in system Stop mode ; ; IWDG_FZ_SDBY=0|1 is programming IWDG_FZ_SDBY bit of user option byte ; 0: Independent watchdog counter is frozen in Standby mode ; 1: Independent watchdog counter is running in Standby mode ; ; IWDG_STDBY=0|1 is programming IWDG_STDBY bit of user option byte ; ; ST_RAM_SIZE=0..3 is programming ST RAM size ; 0: 2 Kbytes reserved to ST code ; 1: 4 Kbytes reserved to ST code ; 2: 8 Kbytes reserved to ST code ; 3: 16 Kbytes reserved to ST code ; ; SECURITY=0|1: Manage secure access mode ; 0: Security feature disabled ; 1: Security feature enabled ; ; IO_HSLV: I/O high-speed at low-voltage configuration ; 0: I/O speed optimization at low-voltage disabled ; 1: I/O speed optimization at low-voltage feature allowed ; ; SWAP_BANK_OPT: Bank swapping option ; 0: bank 1 and bank 2 not swapped ; 1: bank 1 and bank 2 swapped ; ; BOOT_ADD0= MSB of the Arm Cortex-M7 boot address when ; the BOOT pin is low ; BOOT_ADD1= MSB of the Arm Cortex-M7 boot address when ; the BOOT pin is high ; ; PROT_AREA_END1=: Bank 1 PCROP area end offset ; ; DMEP1: Bank 1 PCROP protected erase enable bit ; 0: Bank 1 PCROP area is not erased while a protection level regression ; 1: Bank 1 PCROP area is erased while a protection level regression ; ; PROT_AREA_START1=: Bank 1 PCROP area start offset ; ; PROT_AREA_END2=: Bank 2 PCROP area end offset ; ; DMEP2: Bank 2 PCROP protected erase enable bit ; 0: Bank 1 PCROP area is not erased ; 1: Bank 1 PCROP area is erased ; ; PROT_AREA_START2=: Bank 2 PCROP area start offset ; ; SEC_AREA_END1=: Bank 1 secure-only area end offset ; ; DMES1: Bank 1 secure access protected erase enable bit ; 0: Secure access only area in bank 1 is not erased ; 1: Secure access only area in bank 1 is erased ; ; SEC_AREA_START1=: Bank 1 secure-only area start offset ; ; SEC_AREA_END2=: Bank 2 secure-only area end offset ; ; DMES2: Bank 2 secure access protected erase enable bit ; 0: Secure access only area in bank 2 is not erased ; 1: Secure access only area in bank 2 is erased ; ; SEC_AREA_START2=: Bank 2 secure-only area start offset ; ; WRPSn1=: Bank 1 sector write protection option status byte ; ; WRPSn2=: Bank 2 sector write protection option status byte ; ; RESETDEVICE Activate Flash Settings ; ; @Author: NEZ ; @Copyright: (C) 1989-2023 Lauterbach GmbH, licensed for use with TRACE32(R) only ; -------------------------------------------------------------------------------- ; $Rev: 12927 $ ; $Id: stm32h7-optionbyte.cmm 12927 2024-01-12 11:00:05Z nzouari $ LOCAL ¶meters ENTRY %LINE ¶meters ; LOCAL macros used as script global macros LOCAL &Script LOCAL &FlashRegBase &FlashAdressStart &FlashSize //Option Bytes LOCAL &OB_OPTSR_CUR &OB_OPTSR_PRG LOCAL &OB_PRAR_CUR1 &OB_PRAR_CUR2 &OB_PRAR_PRG1 &OB_PRAR_PRG2 LOCAL &OB_SCAR_CUR1 &OB_SCAR_CUR2 &OB_SCAR_PRG1 &OB_SCAR_PRG2 LOCAL &OB_WPSN_CUR1R &OB_WPSN_CUR2R &OB_WPSN_PRG1R &OB_WPSN_PRG2R LOCAL &OB_BOOT_CUR &OB_BOOT_PRG LOCAL &dualbank &pcrop_granularity &Script=OS.PPF() &FlashRegBase="D:0x52002000" &FlashAdressStart="0x8000000" ; Checking CPU selection IF !CPUIS(STM32H7*) ( SYStem.RESet SYStem.CPU STM32H7* ) IF !(CPUIS(STM32H742*)||CPUIS(STM32H743*)||CPUIS(STM32H753*)||CPUIS(STM32H750*)) ( PRINT %ERROR "CPU not supported by this script" ENDDO ) IF SYStem.MODE()<5 ( IF CABLE.TWOWIRE() SYStem.CONFIG.DEBUGPORTTYPE SWD SYStem.Option.ResBreak OFF SYStem.Up ) IF CPUIS(STM32H750*B) ( &FlashSize=0x20000 &dualbank=FALSE() ) ELSE IF (CPUIS(STM32H742*I)||CPUIS(STM32H743*I)||CPUIS(STM32H753*I)) ( &FlashSize=0x200000 &dualbank=TRUE() ) ELSE IF (CPUIS(STM32H742*G)||CPUIS(STM32H743*G)||CPUIS(STM32H753*G)) ( &FlashSize=0x100000 &dualbank=TRUE() ) &pcrop_granularity=0x100 //256Byte ; Parse script arguments IF "¶meters"=="" ( PRINT %ERROR "Script parameters are missing. Please refer to the script's header " ENDDO ) ELSE ( PRIVATE ¶m_BOR_LEV ¶m_IWDG1_SW PRIVATE ¶m_NRST_STOP_D1 ¶m_NRST_STDBY_D1 PRIVATE ¶m_RDP ¶m_IWDG_FZ_STOP ¶m_IWDG_FZ_SDBY PRIVATE ¶m_ST_RAM_SIZE ¶m_SECURITY ¶m_IO_HSLV PRIVATE ¶m_SWAP_BANK_OPT ¶m_BOOT_ADD0 ¶m_BOOT_ADD1 PRIVATE ¶m_PROT_AREA_END1 ¶m_DMEP1 ¶m_PROT_AREA_START1 PRIVATE ¶m_PROT_AREA_END2 ¶m_DMEP2 ¶m_PROT_AREA_START2 PRIVATE ¶m_SEC_AREA_END1 ¶m_DMES1 ¶m_SEC_AREA_START1 PRIVATE ¶m_SEC_AREA_END2 ¶m_DMES2 ¶m_SEC_AREA_START2 PRIVATE ¶m_WRPSn1 ¶m_WRPSn2 PRIVATE ¶m_resetDevice &programFlash ¶m_BOR_LEV=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"BOR_LEV=","") ¶m_IWDG1_SW=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"IWDG1_SW=","") ¶m_NRST_STOP_D1=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"NRST_STOP_D1=","") ¶m_NRST_STDBY_D1=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"NRST_STDBY_D1=","") ¶m_RDP=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"RDP=","") ¶m_IWDG_FZ_STOP=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"IWDG_FZ_STOP=","") ¶m_IWDG_FZ_SDBY=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"IWDG_FZ_SDBY=","") ¶m_ST_RAM_SIZE=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"ST_RAM_SIZE=","") ¶m_SECURITY=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"SECURITY=","") ¶m_IO_HSLV=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"IO_HSLV=","") ¶m_SWAP_BANK_OPT=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"SWAP_BANK_OPT=","") ¶m_BOOT_ADD0=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"BOOT_ADD0=","") ¶m_BOOT_ADD1=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"BOOT_ADD1=","") ¶m_PROT_AREA_END1=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"PROT_AREA_END1=","") ¶m_DMEP1=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"DMEP1=","") ¶m_PROT_AREA_START1=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"PROT_AREA_START1=","") ¶m_PROT_AREA_END2=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"PROT_AREA_END2=","") ¶m_DMEP2=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"DMEP2=","") ¶m_PROT_AREA_START2=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"PROT_AREA_START2=","") ¶m_SEC_AREA_END1=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"SEC_AREA_END1=","") ¶m_DMES1=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"DMES1=","") ¶m_SEC_AREA_START1=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"SEC_AREA_START1=","") ¶m_SEC_AREA_END2=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"SEC_AREA_END2=","") ¶m_DMES2=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"DMES2=","") ¶m_SEC_AREA_START2=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"SEC_AREA_START2=","") ¶m_WRPSn1=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"WRPSN1=","") ¶m_WRPSn2=STRing.SCANAndExtract(STRing.UPpeR("¶meters"),"WRPSN2=","") ¶m_resetDevice=(STRing.SCAN(STRing.UPpeR("¶meters"),"RESETDEVICE",0)!=-1) &programFlash=FALSE() GOSUB ReadOptionBytes IF "¶m_BOR_LEV"=="3" ( &OB_OPTSR_PRG=(&OB_OPTSR_CUR&0xFFFFFFF3)|(0x3<<2.) ) ELSE IF "¶m_BOR_LEV"=="2" ( &OB_OPTSR_PRG=(&OB_OPTSR_CUR&0xFFFFFFF3)|(0x2<<2.) ) ELSE IF "¶m_BOR_LEV"=="1" ( &OB_OPTSR_PRG=(&OB_OPTSR_CUR&0xFFFFFFF3)|(0x1<<2.) ) ELSE IF "¶m_BOR_LEV"=="0" ( &OB_OPTSR_PRG=(&OB_OPTSR_CUR&0xFFFFFFF3)|(0x0<<2.) ) &programFlash=TRUE() IF "¶m_IWDG1_SW"!="" ( IF "¶m_IWDG1_SW"=="1" &OB_OPTSR_PRG=&OB_OPTSR_CUR|0x10 ELSE IF "¶m_IWDG1_SW"=="0" &OB_OPTSR_PRG=&OB_OPTSR_CUR&~0x10 &programFlash=TRUE() ) IF "¶m_NRST_STOP_D1"!="" ( IF "¶m_NRST_STOP_D1"=="1" &OB_OPTSR_PRG=&OB_OPTSR_CUR|0x40 ELSE IF "¶m_NRST_STOP_D1"=="0" &OB_OPTSR_PRG=&OB_OPTSR_CUR&~0x40 &programFlash=TRUE() ) IF "¶m_NRST_STDBY_D1"!="" ( IF "¶m_NRST_STDBY_D1"=="1" &OB_OPTSR_PRG=&OB_OPTSR_CUR|0x80 ELSE IF "¶m_NRST_STDBY_D1"=="0" &OB_OPTSR_PRG=&OB_OPTSR_CUR&~0x80 &programFlash=TRUE() ) IF "¶m_RDP"!="" ( IF "¶m_RDP"=="1" &OB_OPTSR_PRG=(&OB_OPTSR_CUR&0xFFFF00FF)|(0xFF<<8.) ELSE IF "¶m_RDP"=="0" &OB_OPTSR_PRG=(&OB_OPTSR_CUR&0xFFFF00FF)|(0xAA<<8.) &programFlash=TRUE() ) IF "¶m_IWDG_FZ_STOP"!="" ( IF "¶m_IWDG_FZ_STOP"=="1" &OB_OPTSR_PRG=&OB_OPTSR_CUR|0x20000 ELSE IF "¶m_IWDG_FZ_STOP"=="0" &OB_OPTSR_PRG=&OB_OPTSR_CUR&~0x20000 &programFlash=TRUE() ) IF "¶m_IWDG_FZ_SDBY"!="" ( IF "¶m_IWDG_FZ_SDBY"=="1" &OB_OPTSR_PRG=&OB_OPTSR_CUR|0x40000 ELSE IF "¶m_IWDG_FZ_SDBY"=="0" &OB_OPTSR_PRG=&OB_OPTSR_CUR&~0x40000 &programFlash=TRUE() ) IF "¶m_ST_RAM_SIZE"=="3" ( &OB_OPTSR_PRG=&OB_OPTSR_CUR&0xFFE7FFFF &OB_OPTSR_PRG=&OB_OPTSR_CUR|0x000C ) ELSE IF "¶m_ST_RAM_SIZE"=="2" ( &OB_OPTSR_PRG=&OB_OPTSR_CUR&0xFFE7FFFF &OBH_OPTSR_PRG=&OB_OPTSR_CUR|0x0004 ) ELSE IF "¶m_ST_RAM_SIZE"=="1" ( &OB_OPTSR_PRG=&OB_OPTSR_CUR&0xFFE7FFFF &OB_OPTSR_PRG=&OB_OPTSR_CUR|0x0001 ) ELSE IF "¶m_ST_RAM_SIZE"=="0" ( &OB_OPTSR_PRG=&OB_OPTSR_CUR&0xFFE7FFFF &OB_OPTSR_PRG=&OB_OPTSR_CUR|0x0000 ) &programFlash=TRUE() IF "¶m_SECURITY"!="" ( IF "¶m_SECURITY"=="1" &OB_OPTSR_PRG=&OB_OPTSR_CUR|0x200000 ELSE IF "¶m_SECURITY"=="0" &OB_OPTSR_PRG=&OB_OPTSR_CUR&~0x200000 &programFlash=TRUE() ) IF "¶m_IO_HSLV"!="" ( IF "¶m_IO_HSLV"=="1" &OB_OPTSR_PRG=&OB_OPTSR_CUR|20000000 ELSE IF "¶m_IO_HSLV"=="0" &OB_OPTSR_PRG=&OB_OPTSR_CUR~0x20000000 &programFlash=TRUE() ) IF "¶m_SWAP_BANK_OPT"!="" ( IF "¶m_SWAP_BANK_OPT"=="1" &OB_OPTSR_PRG=&OB_OPTSR_CUR&~0x80000000 ELSE IF "¶m_SWAP_BANK_OPT"=="0" &OB_OPTSR_PRG=&OB_OPTSR_CUR|0x80000000 &programFlash=TRUE() ) IF ("¶m_BOOT_ADD0"!="") ( &OB_BOOT_PRG=(&OB_BOOT_CUR&0xFFFF0000)|(¶m_BOOT_ADD0) &programFlash=TRUE() ) IF ("¶m_BOOT_ADD1"!="") ( &OB_BOOT_PRG=(&OB_BOOT_CUR&0x0000FFFF)|(¶m_BOOT_ADD1<<16.) &programFlash=TRUE() ) IF ("¶m_PROT_AREA_END1"!="") ( &OB_PRAR_PRG1=(&OB_PRAR_CUR1&0xF000FFFF)|(¶m_PROT_AREA_END1<<16.) &programFlash=TRUE() ) IF ("¶m_PROT_AREA_START1"!="") ( &OB_PRAR_PRG1=(&OB_PRAR_CUR1&0xFFFFF000)|(¶m_PROT_AREA_START1&0xFFF) &programFlash=TRUE() ) IF "¶m_DMEP1"!="" ( IF "¶m_DMEP1"=="1" &OB_PRAR_PRG1=&OB_PRAR_CUR1|0x80000000 ELSE IF "¶m_DMEP1"=="0" &OB_PRAR_PRG1=&OB_PRAR_CUR1&~0x80000000 &programFlash=TRUE() ) IF ("¶m_PROT_AREA_END2"!="") ( &OB_PRAR_PRG2=(&OB_PRAR_CUR2&0xF000FFFF)|(¶m_PROT_AREA_END2<<16.) &programFlash=TRUE() ) IF ("¶m_PROT_AREA_START2"!="") ( &OB_PRAR_PRG2=(&OB_PRAR_CUR2&0xFFFFF000)|(¶m_PROT_AREA_START2&0xFFF) &programFlash=TRUE() ) IF ("¶m_DMEP2"!="") ( IF "¶m_DMEP2"=="1" &OB_PRAR_PRG2=&OB_PRAR_CUR2|0x80000000 ELSE IF "¶m_DMEP2"=="0" &OB_PRAR_PRG2=&OB_PRAR_CUR2&~0x80000000 &programFlash=TRUE() ) IF ("¶m_SEC_AREA_END1"!="") ( &OB_SCAR_PRG1=(&OB_SCAR_CUR1&0xF000FFFF)|(¶m_SEC_AREA_END1<<16.) &programFlash=TRUE() ) IF ("¶m_SEC_AREA_START1"!="") ( &OB_SCAR_PRG1=(&OB_SCAR_CUR1&0xFFFFF000)|(¶m_SEC_AREA_START1&0xFFF) &programFlash=TRUE() ) IF "¶m_DMES1"!="" ( IF "¶m_DMES1"=="1" &OB_SCAR_PRG1=&OB_SCAR_CUR1|0x80000000 ELSE IF "¶m_DMES1"=="0" &OB_SCAR_PRG1=&OB_SCAR_CUR1&~0x80000000 &programFlash=TRUE() ) IF ("¶m_SEC_AREA_END2"!="") ( &OB_SCAR_PRG2=(&OB_SCAR_CUR2&0xF000FFFF)|(¶m_SEC_AREA_END2<<16.) &programFlash=TRUE() ) IF ("¶m_SEC_AREA_START2"!="") ( &OB_SCAR_PRG2=(&OB_SCAR_CUR2&0xFFFFF000)|(¶m_SEC_AREA_START2&0xFFF) &programFlash=TRUE() ) IF "¶m_DMES2"!="" ( IF "¶m_DMES2"=="1" &OB_SCAR_PRG2=&OB_SCAR_CUR2|0x80000000 ELSE IF "¶m_DMES2"=="0" &OB_SCAR_PRG2=&OB_SCAR_CUR2&~0x80000000 &programFlash=TRUE() ) IF ("¶m_WRPSn1"!="") ( &OB_WPSN_PRG1R=(&OB_WPSN_CUR1R&0xFFFFFF00)|(¶m_WRPSn1&0xFF) &programFlash=TRUE() ) IF ("¶m_WRPSn2"!="") ( &OB_WPSN_PRG2R=(&OB_WPSN_CUR2R&0xFFFFFF00)|(¶m_WRPSn2&0xFF) &programFlash=TRUE() ) ; Program option bytes into flash IF &programFlash ( GOSUB ProgramOptionBytes ; Reset device to activate programmed option bytes IF ¶m_resetDevice GOSUB ResetDevice ) ELSE ( PRINT %ERROR "Option bytes programming not yet done" ) ) ENDDO ; -------------------------------------------------------------------------------- ; Reset device ResetDevice: ( SYStem.Down SYStem.Up RETURN ) ; -------------------------------------------------------------------------------- ; Read option byte values out of flash ReadOptionBytes: ( &OB_OPTSR_CUR=Data.Long(&FlashRegBase+0x01C) &OB_PRAR_CUR1=Data.Long(&FlashRegBase+0x028) &OB_PRAR_CUR2=Data.Long(&FlashRegBase+0x128) &OB_SCAR_CUR1=Data.Long(&FlashRegBase+0x030) &OB_SCAR_CUR2=Data.Long(&FlashRegBase+0x130) &OB_WPSN_CUR1R=Data.Long(&FlashRegBase+0x038) &OB_WPSN_CUR2R=Data.Long(&FlashRegBase+0x138) &OB_BOOT_CUR=Data.Long(&FlashRegBase+0x040) RETURN ) ; -------------------------------------------------------------------------------- ; Program option bytes ProgramOptionBytes: ( PRIVATE &cr1 &cr2 &optcr &cr1=Data.Long(&FlashRegBase+0xC) &cr2=Data.Long(&FlashRegBase+0x10C) ; Unlock FLASH_CR1 Register IF ((&cr1&0x1)==0x1) ( Data.Set &FlashRegBase+0x004 %Long 0x45670123 // FLASH->KEYR1 = FLASH_KEY1; Data.Set &FlashRegBase+0x004 %Long 0xCDEF89AB // FLASH->KEYR1 = FLASH_KEY2; ) ; Unlock FLASH_CR2 Register IF ((&cr2&0x1)==0x1) ( Data.Set &FlashRegBase+0x104 %Long 0x45670123 // FLASH->KEYR2 = FLASH_KEY1; Data.Set &FlashRegBase+0x104 %Long 0xCDEF89AB // FLASH->KEYR2 = FLASH_KEY2; ) ; Unlock FLASH_OPTCR Register Data.Set &FlashRegBase+0x108 %Long 0x08192A3B // FLASH->OPTKEYR = FLASH_KEY1; Data.Set &FlashRegBase+0x108 %Long 0x4C5D6E7F // FLASH->OPTKEYR = FLASH_KEY2; &optlocked=Data.Long(&FlashRegBase+0x018)&0x1 // locked = FLASH->OTPCR & OPTLOCK IF (&optlocked==0x1) ( PRINT %ERROR "Cannot unlock option byte programming!" RETURN ) IF (((&OB_OPTSR_CUR&0xFF00)>>8.)==0xCC) ( PRINT "Option byte programming aborted, because RDP=0xCC will disable further debugging" PRINT "Disabling JTAG won't be reversible" Data.Set &FlashRegBase+0xC %Long &cr1 // restore FLASH_CR1 register Data.Set &FlashRegBase+0x10C %Long &cr2 // restore FLASH_CR2 register ENDDO ) ; Start option byte programming Data.Set &FlashRegBase+0x20 %Long &OB_OPTSR_PRG Data.Set &FlashRegBase+0x2C %Long &OB_PRAR_PRG1 Data.Set &FlashRegBase+0x12C %Long &OB_PRAR_PRG2 Data.Set &FlashRegBase+0x34 %Long &OB_SCAR_PRG1 Data.Set &FlashRegBase+0x134 %Long &OB_SCAR_PRG2 Data.Set &FlashRegBase+0x3C %Long &OB_WPSN_PRG1R Data.Set &FlashRegBase+0x13C %Long &OB_WPSN_PRG2R Data.Set &FlashRegBase+0x44 %Long &OB_BOOT_PRG ; Set OPTSTART bit to 1 in the FLASH_OPTCR register &optcr=Data.Long(&FlashRegBase+0x18) Data.Set &FlashRegBase+0x18 %Long (&optcr)|(1<<1.) WAIT 1s ;Restore FLASH_CR1 and FLASH_CR2 registers Data.Set &FlashRegBase+0xC %Long &cr1 Data.Set &FlashRegBase+0x10C %Long &cr2 ¶m_resetDevice=TRUE() RETURN )