Files
Gen4_R-Car_Trace32/2_Trunk/demo/arm/flash/stm32l0xx-optionbyte.cmm
2025-10-14 09:52:32 +09:00

699 lines
19 KiB
Plaintext

; --------------------------------------------------------------------------------
; @Title: ST STM32L0xx Flash Dialog to program Option Bytes.
;
; @Description:
; Script arguments:
;
; do stm32l0xx-optionbyte [RDP=0|1|NODEBUG]
; [NBOOT1=0|1]
; [BFB2=0|1] [NRST_STDBY=0|1] [NRST_STOP=0|1] [WDG_SW=0|1]
; [BOR_LEV=<val>]
; [WPRMOD=0|1]
; [WRPROT1=<val>]
; [WRPROT2=<val>]
; [RESETDEVICE]
;
; RDP=0|1|NODEBUG programs the read protection option byte
; 0: disables flash read protection
; 1: enables flash read protection
; NODEBUG: no debug
;
; NBOOT1=0|1 selects the boot source with the BOOT0 input pad
; X: When BOOT0 = 0, boot to flash program memory
; 0: When BOOT0 = 1, boot to RAM
; 1: When BOOT0 = 1, boot to system memory
; At RDP level 2 (NODEBUG), the boot source is always flash.
;
; BFB2=0|1 sets the bit to boot from bank 2 (see documentation)
; 0: Boot from Bank 1 (cat 5 device) or user flash memory
; 1: Boot from system memory
;
; NRST_STDBY=0|1
; 0: Reset generated when entering Standby mode
; 1: No reset generated when entering Standby mode
;
; NRST_STOP=0|1
; 0: Reset generated when entering Stop mode
; 1: No reset generated when entering Stop mode
;
; WDG_SW=0|1
; 0: Hardware watchdog
; 1: Software watchdog
;
; BOR_LEV=<val> sets the brown out threshold level
; 1000: BOR LEVEL 1 = reset threshold 1.8 V
; 1001: BOR LEVEL 2 = reset threshold 2.0 V
; 1010: BOR LEVEL 3 = reset threshold 2.5 V
; 1011: BOR LEVEL 4 = reset threshold 2.7 V
; 1100: BOR LEVEL 5 = reset threshold 3.0 V
; 0XXX: BOR OFF = reset threshold 1.45--1.55--1.65 V
;
; WPRMOD=0|1 sets the sector protection mode (either read or write)
; 0: PCROP disabled; WRPROT bits determine write protection
; 1: PCROP enabled; WRPROT bits determine read protection
;
; WRPROT1=<val> sets a 32-bit write protection register (each bit 4 Kb)
; 0: (at any offset) sector unprotected
; 1: (at any offset) sector protected
;
; WRPROT2=<val> sets a 16-bit write protection register (each bit 4 Kb)
; 0: (at any offset) sector unprotected
; 1: (at any offset) sector protected
;
; RESETDEVICE resets the device after option byte programming
;
; Calling the script without argument starts the Option Byte programming
; dialog window.
;
; @Author: BWR
; @Copyright: (C) 1989-2022 Lauterbach GmbH, licensed for use with TRACE32(R) only
; --------------------------------------------------------------------------------
; $Rev: 10516 $
; $Id: stm32l0xx-optionbyte.cmm 10516 2022-02-02 11:39:30Z bschroefel $
PRIVATE &parameters
ENTRY %LINE &parameters
; PRIVATE macros used as script global macros
LOCAL &FlashRegBase ; Flash controller base address
LOCAL &FlashAddress ; Main flash start address
LOCAL &OptionByteBase ; Option byte base address
LOCAL &FlashSize ; Flash size
&FlashRegBase="D:0x40022000"
&OptionByteBase="D:0x1FF80000"
&FlashAddress="0x08000000" ; used for calculation only therefore without D:
LOCAL &OptByte_RDP &OptByte_USER &OptByte_WRPROT1 &OptByte_WRPROT2
&OptByte_RDP=0xAA
&OptByte_USER=0x807000
&OptByte_WRPROT1=0x00000000
&OptByte_WRPROT2=0x0000
; Look for any opened STM32L0xx dialog windows and close them
WHILE DIALOG.EXIST(COMB_BOR_LEV)
DIALOG.END
; Checking CPU selection
IF !CPUIS(STM32L0*)
SYStem.CPU STM32L0*
; Check system mode
IF SYStem.MODE()<5.
SYStem.Up
; Setup configuration for CPU derivative
IF CPUIS("STM32L0???3*")
(
&FlashSize=0x2000
)
ELSE IF CPUIS("STM32L0???4*")
(
&FlashSize=0x4000
)
ELSE IF CPUIS("STM32L0???6*")
(
&FlashSize=0x8000
)
ELSE IF CPUIS("STM32L0???8*")
(
&FlashSize=0x10000
)
ELSE IF CPUIS("STM32L0???B*")
(
&FlashSize=0x20000
)
ELSE IF CPUIS("STM32L0???Z*")
(
&FlashSize=0x30000
)
ELSE
(
DIALOG.OK SYStem.CPU()+" is not supported by the script"
ENDDO
)
; Parse script arguments
IF "&parameters"==""
(
;PRINT "Call script with parameters: DO stm32l0xx-optionbyte [RDP=0|1|NODEBUG] [NBOOT1=0|1] [BFB2=0|1] [NRST_STDBY=0|1] [NRST_STOP=0|1] [WDG_SW=0|1] [BOR_LEV=<val>] [WPRMOD=0|1] [WRPROT1=<val>] [WRPROT2=<val>] [RESETDEVICE]"
GOSUB OptionByteDialog
)
ELSE
(
PRIVATE &param_WRPROT2 &param_WRPROT1 &param_WPRMOD &param_BOR_LEV &param_WDG_SW &param_NRST_STOP &param_NRST_STDBY &param_BFB2 &param_NBOOT1 &param_RDP &param_resetDevice
&param_RDP=STRing.SCANAndExtract(STRing.UPpeR("&parameters"),"RDP=","")
&param_NBOOT1=STRing.SCANAndExtract(STRing.UPpeR("&parameters"),"NBOOT1=","")
&param_BFB2=STRing.SCANAndExtract(STRing.UPpeR("&parameters"),"BFB2=","")
&param_NRST_STDBY=STRing.SCANAndExtract(STRing.UPpeR("&parameters"),"NRST_STDBY=","")
&param_NRST_STOP=STRing.SCANAndExtract(STRing.UPpeR("&parameters"),"NRST_STOP=","")
&param_WDG_SW=STRing.SCANAndExtract(STRing.UPpeR("&parameters"),"WDG_SW=","")
&param_BOR_LEV=STRing.SCANAndExtract(STRing.UPpeR("&parameters"),"BOR_LEV=","")
&param_WPRMOD=STRing.SCANAndExtract(STRing.UPpeR("&parameters"),"WPRMOD=","")
&param_WRPROT1=STRing.SCANAndExtract(STRing.UPpeR("&parameters"),"WRPROT1=","")
&param_WRPROT2=STRing.SCANAndExtract(STRing.UPpeR("&parameters"),"WRPROT2=","")
&param_resetDevice=(STRing.SCAN(STRing.UPpeR("&parameters"),"RESETDEVICE",0)!=-1)
GOSUB ReadOptionBytes
IF "&param_RDP"!=""
(
IF "&param_RDP"=="0"
&OptByte_RDP=0xAA
ELSE IF "&param_RDP"=="1"
&OptByte_RDP=0x00
ELSE IF "&param_RDP"=="NODEBUG"
&OptByte_RDP=0xCC
ELSE
(
PRINT %ERROR "Illegal parameter RDP="+"&param_RDP"
ENDDO
)
IF (&OptByte_RDP==0xCC)
(
GOSUB QueryNoDebug
ENTRY &nodebug
IF (!&nodebug)
ENDDO
)
)
IF "&param_NBOOT1"!=""
(
IF "&param_NBOOT1"=="1"
&OptByte_USER=&OptByte_USER|0x800000
ELSE IF "&param_NBOOT1"=="0"
&OptByte_USER=&OptByte_USER&0x7FFFFF
ELSE
(
PRINT %ERROR "Illegal parameter NBOOT1="+"&param_NBOOT1"
ENDDO
)
)
IF "&param_BFB2"!=""
(
IF "&param_BFB2"=="1"
&OptByte_USER=&OptByte_USER|0x008000
ELSE IF "&param_BFB2"=="0"
&OptByte_USER=&OptByte_USER&0xFF7FFF
ELSE
(
PRINT %ERROR "Illegal parameter BFB2="+"&param_BFB2"
ENDDO
)
)
IF "&param_NRST_STDBY"!=""
(
IF "&param_NRST_STDBY"=="1"
&OptByte_USER=&OptByte_USER|0x004000
ELSE IF "&param_NRST_STDBY"=="0"
&OptByte_USER=&OptByte_USER&0xFFBFFF
ELSE
(
PRINT %ERROR "Illegal parameter NRST_STDBY="+"&param_NRST_STDBY"
ENDDO
)
)
IF "&param_NRST_STOP"!=""
(
IF "&param_NRST_STOP"=="1"
&OptByte_USER=&OptByte_USER|0x002000
ELSE IF "&param_NRST_STOP"=="0"
&OptByte_USER=&OptByte_USER&0xFFDFFF
ELSE
(
PRINT %ERROR "Illegal parameter NRST_STOP="+"&param_NRST_STOP"
ENDDO
)
)
IF "&param_WDG_SW"!=""
(
IF "&param_WDG_SW"=="1"
&OptByte_USER=&OptByte_USER|0x001000
ELSE IF "&param_WDG_SW"=="0"
&OptByte_USER=&OptByte_USER&0xFFEFFF
ELSE
(
PRINT %ERROR "Illegal parameter WDG_SW="+"&param_WDG_SW"
ENDDO
)
)
IF "&param_BOR_LEV"!=""
(
IF (&param_BOR_LEV>0xC||&param_BOR_LEV<0x0)
(
PRINT %ERROR "Illegal parameter BOR_LEV="+"&PARAM_BOR_LEV" "! BOR_LEV is out of range! " "BOR_LEV must be a 4-bit unsigned numeric value"
ENDDO
)
; Set any BOR OFF value to 0x0
IF (&param_BOR_LEV<0x8)
&param_BOR_LEV=0x0
&OptByte_USER=(&OptByte_USER&0xFFF0FF)|(&param_BOR_LEV<<8.)
)
IF "&param_WPRMOD"!=""
(
IF "&param_WPRMOD"=="1"
&OptByte_USER=&OptByte_USER|0x000001
ELSE IF "&param_WPRMOD"=="0"
&OptByte_USER=&OptByte_USER&0xFFFFFE
ELSE
(
PRINT %ERROR "Illegal parameter WPRMOD="+"&param_WPRMOD"
ENDDO
)
)
IF "&param_WRPROT1"!=""
(
&OptByte_WRPROT1=&param_WRPROT1&0xFFFFFFFF
)
IF "&param_WRPROT2"!=""
(
&OptByte_WRPROT2=&param_WRPROT2&0x0000FFFF
)
; Program option bytes into flash
GOSUB ProgramOptionBytes
; Reset device to activate programmed option bytes
IF &param_resetDevice
GOSUB ResetDevice
)
ENDDO
; --------------------------------------------------------------------------------
; NVM bit programming dialog window
OptionByteDialog:
(
; Creating the main dialog. (& after DIALOG command must be in first column!
WinPOS 50. 5. 68. 18.
DIALOG.view
(&
HEADER SYStem.CPU()+" option bytes"
POS 1. 0. 66. 3.
BOX "Read protection level"
POS 3. 1. 20. 1.
CHSB_RDP.OFF: CHOOSEBOX "no read protection" ""
POS 24. 1. 20. 1.
CHSB_RDP.ON: CHOOSEBOX "read protection" ""
POS 45. 1. 20. 1.
CHSB_RDP.NODBG: CHOOSEBOX "no debug" "GOSUB SelectNoDebug"
POS 1. 3. 66. 13.
BOX "User option bytes"
POS 3. 4. 29. 1.
CHSB_WPRMOD.W: CHOOSEBOX "WRPROT = sector write protection" ""
CHSB_WPRMOD.R: CHOOSEBOX "WRPROT = sector read protection" ""
POS 33. 4. 8. 1.
TEXT "WRPROT1:"
TEXT "WRPROT2:"
POS 41. 4. 15. 1.
EDIT_WRPROT1: EDIT "0x00000000" ""
POS 41. 5. 10. 1.
EDIT_WRPROT2: EDIT "0x0000" ""
POS 3. 7. 20. 1.
TEXT "Brownout Threshold Level:"
POS 24. 7. 20. 1.
COMB_BOR_LEV: COMBOBOX "Level 1: around 1.8 V,Level 2: around 2.0 V,Level 3: around 2.5 V,Level 4: around 2.7 V,Level 5: around 3.0 V,Off: below 1.65 V" ""
POS 3. 9. 20. 1.
CHSB_WDG.HW: CHOOSEBOX "Hardware watchdog" ""
CHSB_WDG.SW: CHOOSEBOX "Software watchdog" ""
POS 3. 12. 29. 1.
CHK_NRST_STOP: CHECKBOX "Generate reset entering Stop mode" ""
CHK_NRST_STDBY: CHECKBOX "Generate reset entering Standby mode" ""
POS 33. 10. 31. 1.
CHK_BFB2: CHECKBOX "Boot from Bank 2 (details in datasheet)" ""
POS 33. 12. 31. 1.
CHSB_NBOOT1.S: CHOOSEBOX "Boot in system memory when BOOT0=0" ""
CHSB_NBOOT1.R: CHOOSEBOX "Boot in embedded SRAM when BOOT0=0" ""
TEXT " (Boot in flash when BOOT0=1)"
POS 1. 16. 13. 1.
BUTTON "Program flash" "GOSUB ProgramFlashSettings"
POS 21. 16. 13. 1.
BUTTON "Reset device" "GOSUB ActivateFlashSettings"
POS 41. 16. 10. 1.
BUTTON "Refresh" "GOSUB UpdateWindowFromFlashContents"
POS 58. 16. 9. 1.
BUTTON "Exit" "CONTinue"
CLOSE "CONTinue"
)
; Select/deselect each UI element
GOSUB UpdateWindowFromFlashContents
STOP
DIALOG.END
ENDDO
)
SelectNoDebug:
(
PRIVATE &result
IF &OptByte_RDP!=0xCC
(
GOSUB QueryNoDebug
ENTRY &result
IF !&result
(
IF &OptByte_RDP==0xAA
DIALOG.Set CHSB_RDP.OFF "ON"
ELSE IF &OptByte_RDP==0xCC
DIALOG.Set CHSB_RDP.NODBG "ON"
ELSE
DIALOG.Set CHSB_RDP.ON "ON"
)
)
RETURN
)
; --------------------------------------------------------------------------------
; Read out option bytes and set dialog entries
UpdateWindowFromFlashContents:
(
GOSUB ReadOptionBytes
; Get read protection
IF &OptByte_RDP==0xAA
DIALOG.Set CHSB_RDP.OFF "ON"
ELSE IF &OptByte_RDP==0xCC
DIALOG.Set CHSB_RDP.NODBG "ON"
ELSE
DIALOG.Set CHSB_RDP.ON "ON"
; Get user option byte settings
IF (&OptByte_USER&0x1)==0x0
DIALOG.Set CHSB_WPRMOD.W "ON"
ELSE
DIALOG.Set CHSB_WPRMOD.R "ON"
DIALOG.Set EDIT_WRPROT1 "&OptByte_WRPROT1"
DIALOG.Set EDIT_WRPROT2 "&OptByte_WRPROT2"
IF ((&OptByte_USER>>8.)&0xF)==0x8
DIALOG.Set COMB_BOR_LEV "Level 1: around 1.8 V"
ELSE IF ((&OptByte_USER>>8.)&0xF)==0x9
DIALOG.Set COMB_BOR_LEV "Level 2: around 2.0 V"
ELSE IF ((&OptByte_USER>>8.)&0xF)==0xA
DIALOG.Set COMB_BOR_LEV "Level 3: around 2.5 V"
ELSE IF ((&OptByte_USER>>8.)&0xF)==0xB
DIALOG.Set COMB_BOR_LEV "Level 4: around 2.7 V"
ELSE IF ((&OptByte_USER>>8.)&0xF)==0xC
DIALOG.Set COMB_BOR_LEV "Level 5: around 3.0 V"
ELSE
DIALOG.Set COMB_BOR_LEV "Off: below 1.65 V"
IF ((&OptByte_USER>>12.)&0x1)==0x0
DIALOG.Set CHSB_WDG.HW "ON"
ELSE
DIALOG.Set CHSB_WDG.SW "ON"
IF ((&OptByte_USER>>13.)&0x1)==0x0
DIALOG.Set CHK_NRST_STOP "ON"
ELSE
DIALOG.Set CHK_NRST_STOP "OFF"
IF ((&OptByte_USER>>14.)&0x1)==0x0
DIALOG.Set CHK_NRST_STDBY "ON"
ELSE
DIALOG.Set CHK_NRST_STDBY "OFF"
IF ((&OptByte_USER>>15.)&0x1)==0x1
DIALOG.Set CHK_BFB2 "ON"
ELSE
DIALOG.Set CHK_BFB2 "OFF"
IF ((&OptByte_USER>>23.)&0x1)==0x1
DIALOG.Set CHSB_NBOOT1.S "ON"
ELSE
DIALOG.Set CHSB_NBOOT1.R "ON"
RETURN
)
; --------------------------------------------------------------------------------
; Check user data value
QueryNoDebug:
PRIVATE &result
DIALOG.YESNO "Are you really sure you want to disable DEBUG mode?" "Read protection level 2 cannot be removed at all:" "I T I S A N I R R E V E R S I B L E O P E R A T I O N !"
ENTRY &result
RETURN &result
; --------------------------------------------------------------------------------
; Programming Option Bytes
ProgramFlashSettings:
(
PRIVATE &queryResult &value &programFlash
&programFlash=FALSE()
; Set read protection option byte
IF (DIALOG.BOOLEAN("CHSB_RDP.OFF")&&(&OptByte_RDP!=0xAA))
(
&OptByte_RDP=0xAA
&programFlash=TRUE()
)
ELSE IF DIALOG.BOOLEAN("CHSB_RDP.NODBG")
(
PRIVATE &queryResult
GOSUB QueryNoDebug
ENTRY &queryResult
IF &queryResult
(
&OptByte_RDP=0xCC
&programFlash=TRUE()
)
ELSE
(
PRINT %ERROR "Option byte programming aborted"
RETURN
)
)
ELSE IF (DIALOG.BOOLEAN("CHSB_RDP.ON")&&(&OptByte_RDP!=0x00))
(
&OptByte_RDP=0x00
&programFlash=TRUE()
)
; Set user option bytes
PRIVATE &currentUSER
&currentUSER=&OptByte_USER
IF DIALOG.BOOLEAN(CHSB_WPRMOD.W)
&OptByte_USER=&OptByte_USER&~0x000001
ELSE
&OptByte_USER=&OptByte_USER|0x000001
&OptByte_USER=&OptByte_USER&~0x000F00 ; BOR_LEV mask
IF DIALOG.STRing("COMB_BOR_LEV")=="Level 1: around 1.8 V"
&value=0x8
ELSE IF DIALOG.STRing("COMB_BOR_LEV")=="Level 2: around 2.0 V"
&value=0x9
ELSE IF DIALOG.STRing("COMB_BOR_LEV")=="Level 3: around 2.5 V"
&value=0xA
ELSE IF DIALOG.STRing("COMB_BOR_LEV")=="Level 4: around 2.7 V"
&value=0xB
ELSE IF DIALOG.STRing("COMB_BOR_LEV")=="Level 5: around 3.0 V"
&value=0xC
ELSE ; Off: below 1.65 V
&value=0x0
&OptByte_USER=&OptByte_USER|(&value<<8.)
IF DIALOG.BOOLEAN(CHSB_WDG.HW)
&OptByte_USER=&OptByte_USER&~0x001000
ELSE
&OptByte_USER=&OptByte_USER|0x001000
IF DIALOG.BOOLEAN("CHK_NRST_STOP")
&OptByte_USER=&OptByte_USER&~0x002000
ELSE
&OptByte_USER=&OptByte_USER|0x002000
IF DIALOG.BOOLEAN("CHK_NRST_STDBY")
&OptByte_USER=&OptByte_USER&~0x004000
ELSE
&OptByte_USER=&OptByte_USER|0x004000
IF DIALOG.BOOLEAN("CHK_BFB2")
&OptByte_USER=&OptByte_USER|0x008000
ELSE
&OptByte_USER=&OptByte_USER&~0x008000
IF DIALOG.BOOLEAN(CHSB_NBOOT1.S)
&OptByte_USER=&OptByte_USER|0x800000
ELSE
&OptByte_USER=&OptByte_USER&~0x800000
IF (&OptByte_USER!=&currentUSER)
&programFlash=TRUE()
IF DIALOG.STRing("EDIT_WRPROT1")!=""
&value=DIALOG.STRing(EDIT_WRPROT1)
ELSE
&value=0x00000000
IF (&OptByte_WRPROT1!=&value)
(
&OptByte_WRPROT1=&value
&programFlash=TRUE()
)
IF DIALOG.STRing("EDIT_WRPROT2")!=""
&value=DIALOG.STRing(EDIT_WRPROT2)
ELSE
&value=0x0000
IF (&OptByte_WRPROT2!=&value)
(
&OptByte_WRPROT2=&value
&programFlash=TRUE()
)
IF &programFlash==TRUE()
GOSUB ProgramOptionBytes
RETURN
)
; --------------------------------------------------------------------------------
; Activate programmed flash settings by resetting device
ActivateFlashSettings:
(
GOSUB ResetDevice
GOSUB UpdateWindowFromFlashContents
RETURN
)
; --------------------------------------------------------------------------------
; Reset device
ResetDevice:
(
PRIVATE &pecr
&pecr=Data.Long(&FlashRegBase+0x04)
; Unlock the Flash Control register
IF ((&pecr&0x1)==0x1)
(
Data.Set &FlashRegBase+0x0C %Long 0x89ABCDEF // FLASH->KEYR = FLASH_KEY1;
Data.Set &FlashRegBase+0x0C %Long 0x02030405 // FLASH->KEYR = FLASH_KEY2;
)
; Unlock the option bytes area
IF ((&pecr&0x4)==0x4)
(
Data.Set &FlashRegBase+0x14 %Long 0xFBEAD9C8 // FLASH->OPTKEYR = OPTKEY1;
Data.Set &FlashRegBase+0x14 %Long 0x24252627 // FLASH->OPTKEYR = OPTKEY2;
)
; Set OBL_LAUNCH to power down core (necessary to save option bytes to flash registers)
ON.ERROR CONTINUE
Data.Set &FlashRegBase+0x04 %Long &pecr|(1.<<18.)
WAIT 0.1s
IF (SYStem.UP())
BREAK
ELSE
SYStem.UP
ON.ERROR inherit
RETURN
)
; --------------------------------------------------------------------------------
; Read option byte values out of flash
ReadOptionBytes:
(
PRIVATE &TarOptByte_0 &TarOptByte_1 &TarOptByte_2 &TarOptByte_3 &TarOptByte_4
&TarOptByte_0=Data.Long(&OptionByteBase+0x00)
&TarOptByte_1=Data.Long(&OptionByteBase+0x04)
&TarOptByte_2=Data.Long(&OptionByteBase+0x08)
&TarOptByte_3=Data.Long(&OptionByteBase+0x0C)
&TarOptByte_4=Data.Long(&OptionByteBase+0x10)
&OptByte_RDP=&TarOptByte_0&0x000000FF
&OptByte_USER=(&TarOptByte_1&0xFFFF)<<8.|(&TarOptByte_0&0xFF00)>>8.
&OptByte_WRPROT1=(&TarOptByte_3&0xFFFF)<<16.|(&TarOptByte_2&0xFFFF)
&OptByte_WRPROT2=&TarOptByte_4&0xFFFF
RETURN
)
; --------------------------------------------------------------------------------
; Program option bytes
ProgramOptionBytes:
(
PRIVATE &pecr &value
&pecr=Data.Long(&FlashRegBase+0x04)
; Unlock the Flash Control register
IF ((&pecr&0x1)==0x1)
(
Data.Set &FlashRegBase+0x0C %Long 0x89ABCDEF // FLASH->KEYR = FLASH_KEY1;
Data.Set &FlashRegBase+0x0C %Long 0x02030405 // FLASH->KEYR = FLASH_KEY2;
)
; Unlock the option bytes area
IF ((&pecr&0x4)==0x4)
(
Data.Set &FlashRegBase+0x14 %Long 0xFBEAD9C8 // FLASH->OPTKEYR = OPTKEY1;
Data.Set &FlashRegBase+0x14 %Long 0x24252627 // FLASH->OPTKEYR = OPTKEY2;
)
; Clear all pending flags
Data.Set &FlashRegBase+0x18 %Long 0x00032F0E // FLASH->SR = FWWERR | NOTZEROERR | RDERR | OPTVERR | SIZERR | PGAERR | WRPERR | EOP
; Program option bytes by writing them directly on the address of option byte field + offset
&value=&OptByte_RDP|((&OptByte_USER&0xFF)<<8.)
Data.Set &OptionByteBase+0x00 %Long &value|(~&value<<16.)
WAIT (Data.Long(&FlashRegBase+0x18)&0x00000001)!=0x00000001
&value=(&OptByte_USER&0xFFFF00)>>8.
Data.Set &OptionByteBase+0x04 %Long &value|(~&value<<16.)
WAIT (Data.Long(&FlashRegBase+0x18)&0x00000001)!=0x00000001
&value=&OptByte_WRPROT1&0xFFFF
Data.Set &OptionByteBase+0x08 %Long &value|(~&value<<16.)
WAIT (Data.Long(&FlashRegBase+0x18)&0x00000001)!=0x00000001
&value=(&OptByte_WRPROT1>>16.)&0xFFFF
Data.Set &OptionByteBase+0x0C %Long &value|(~&value<<16.)
WAIT (Data.Long(&FlashRegBase+0x18)&0x00000001)!=0x00000001
&value=&OptByte_WRPROT2&0xFFFF
Data.Set &OptionByteBase+0x10 %Long &value|(~&value<<16.)
WAIT (Data.Long(&FlashRegBase+0x18)&0x00000001)!=0x00000001
; Restore FLASH_PECR register
Data.Set &FlashRegBase+0x04 %Long &pecr
RETURN
)