/******************************************************************************
Target Script for STM32
Copyright (c) 2008, 2010, 2011, 2012 Rowley Associates Limited.
This file may be distributed under the terms of the License Agreement
provided with this software.
THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE
WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
******************************************************************************/
function EnableTrace(TraceInterfaceType)
{
if (TraceInterfaceType == "TracePort")
{
// F2xx/F4xx
switch (TargetInterface.peekWord(0xE0042000) & 0xfff)
{
case 0x412: // STM32F1 low density
case 0x410: // medium density
case 0x414: // high density
case 0x430: // xl density
case 0x418: // connectivity
TargetInterface.pokeWord(0x40021018, TargetInterface.peekWord(0x40021018) | (1<<6)); // RCC_APB2ENR: IO port E clock enable
TargetInterface.pokeWord(0x48011800, 0x00002AA0); // GPIOE_MODER: PE2..PE6 = Alternate function mode
TargetInterface.pokeWord(0x48011808, 0x00001550); // GPIOx_OSPEEDR: PE2..PE6 = 25 MHz Medium speed
TargetInterface.pokeWord(0x4801180C, 0x00001550); // GPIOx_PUPDR: PE2..PE6 = Pull-up
TargetInterface.pokeWord(0x48011820, 0x00000000); // GPIOx_AFRL: PE2..PE6 = AF0
break;
case 0x411: // STM32F2xx
case 0x413: // STM32F40x/STM32F41x
case 0x419: // STM32F42x/STM32F43x
case 0x434: // STM32F469/STM32F479
TargetInterface.pokeWord(0x40023830, TargetInterface.peekWord(0x40023830) | (1<<4)); // RCC_AHB1ENR: IO port E clock enable
TargetInterface.pokeWord(0x40021000, 0x00002AA0); // GPIOE_MODER: PE2..PE6 = Alternate function mode
TargetInterface.pokeWord(0x40021008, 0x00001550); // GPIOx_OSPEEDR: PE2..PE6 = 25 MHz Medium speed
TargetInterface.pokeWord(0x4002100C, 0x00001550); // GPIOx_PUPDR: PE2..PE6 = Pull-up
TargetInterface.pokeWord(0x40021020, 0x00000000); // GPIOx_AFRL: PE2..PE6 = AF0
break;
case 0x422: // STM32F30x
case 0x432: // STM32F37x
case 0x438: // STM32F334/F303/F328
case 0x439: // STM32F30x
case 0x446:
TargetInterface.pokeWord(0x40021014, TargetInterface.peekWord(0x40021014) | (1<<21)); // RCC_AHBENR: IO port E clock enable
TargetInterface.pokeWord(0x48001000, 0x00002AA0); // GPIOE_MODER: PE2..PE6 = Alternate function mode
TargetInterface.pokeWord(0x48001008, 0x00001550); // GPIOx_OSPEEDR: PE2..PE6 = 25 MHz Medium speed
TargetInterface.pokeWord(0x4800100C, 0x00001550); // GPIOx_PUPDR: PE2..PE6 = Pull-up
TargetInterface.pokeWord(0x48001020, 0x00000000); // GPIOx_AFRL: PE2..PE6 = AF0
break;
case 0x416: // STM32L
case 0x427: // medium+
case 0x429:
case 0x436: // high density STM32L
case 0x437: // STM32L152E
TargetInterface.pokeWord(0x4002381C, TargetInterface.peekWord(0x4002381C) | (1<<4)); // RCC_AHBENR: IO port E clock enable
TargetInterface.pokeWord(0x40021000, 0x00002AA0); // GPIOE_MODER: PE2..PE6 = Alternate function mode
TargetInterface.pokeWord(0x40021008, 0x00001550); // GPIOx_OSPEEDR: PE2..PE6 = 25 MHz Medium speed
TargetInterface.pokeWord(0x4002100C, 0x00001550); // GPIOx_PUPDR: PE2..PE6 = Pull-up
TargetInterface.pokeWord(0x40021020, 0x00000000); // GPIOx_AFRL: PE2..PE6 = AF0
break;
}
TargetInterface.pokeWord(0xE0042004, TargetInterface.peekWord(0xE0042004) | 0x000000E0); // DBG_MCU_CR : assign SYNC TRACE I/Os for SIZE=4
}
else if (TraceInterfaceType == "SWO")
TargetInterface.pokeWord(0xE0042004, TargetInterface.peekWord(0xE0042004) | 0x00000020); // DBG_MCU_CR : TRACE_IOEN
}
function Reset()
{
TargetInterface.pokeWord(0xE000EDF0, 0xA05F0003); // set C_HALT and C_DEBUGEN in DHCSR
TargetInterface.waitForDebugState(1000);
var CPUID = TargetInterface.peekWord(0xE000ED00);
if (((CPUID>>4)&0xf)==0) // Cortex-M0
{
TargetInterface.pokeWord(0xE000EDFC, 0x1); // set VC_CORERESET in DEMCR
TargetInterface.pokeWord(0xE000ED0C, 0x05FA0004); // set SYSRESETREQ in AIRCR
TargetInterface.waitForDebugState(1000);
switch ((TargetInterface.peekWord(0x40015800) & 0xfff))
{
case 0x457: // STM32L0x1 - category 1
case 0x425: // STM32L0x1 - category 2
case 0x417: // STM32L0x1/STM32L0x2/STM32L0x3 - category 3
case 0x447: // STM32L0x1/STM32L0x2/STM32L0x3 - category 5
TargetInterface.pokeWord(0x40021034, 1<<22); // DBG_EN
break;
default:
TargetInterface.pokeWord(0x40021018, 1<<22); // DBG_EN
break;
}
TargetInterface.pokeWord(0x40015804, 1<<2|1<<1|1<<0); // enable low-power mode debugging
TargetInterface.pokeWord(0x40015808, 1<<12|1<<11); // turn off WWDG and IWDG in debug mode
}
else if (((CPUID>>4)&0xfff)==0xD21) // Cortex-M33
{
var DBGMCU_IDCODE = TargetInterface.peekWord(0xE0044000);
TargetInterface.pokeWord(0xE000EDFC, 0x1); // set VC_CORERESET in DEMCR
TargetInterface.pokeWord(0xE000ED0C, 0x05FA0004); // set SYSRESETREQ in AIRCR
TargetInterface.waitForDebugState(1000);
switch (DBGMCU_IDCODE & 0xfff)
{
case 0x472: // STM32L5
case 0x482: // STM32U5
TargetInterface.pokeWord(0xE0044004, 1<<2|1<<1); // enable low-power mode debugging
TargetInterface.pokeWord(0xE0044008, 1<<12|1<<11); // turn off WWDG and IWDG in debug mode
break;
default:
break;
}
}
else
{
var DBGMCU_IDCODE = TargetInterface.peekWord(0xE0042000);
TargetInterface.pokeWord(0xE000EDFC, 0x1); // set VC_CORERESET in DEMCR
switch (DBGMCU_IDCODE & 0xffff0fff)
{
case 0x00000410: // STM32F10xx8/STM32F10xxB Revision A devices
case 0x10010414: // STM32F10xxE Revision Z
case 0x20000410: // Some STM32F10xx8/STM32F10xxB Revision B devices are affected
TargetInterface.pokeWord(0xE000ED0C, 0x05FA0001); // set VECTRESET in AIRCR
break;
default:
TargetInterface.pokeWord(0xE000ED0C, 0x05FA0004); // set SYSRESETREQ in AIRCR
break;
}
TargetInterface.waitForDebugState(1000);
switch (DBGMCU_IDCODE & 0xfff)
{
case 0x0: // STM32W108
break;
case 0x411: // STM32F2xx
case 0x413: // STM32F40x/STM32F41x
case 0x415: // STM32L4x1/STM32L4x5/STM32L4x6
case 0x416: // STM32L
case 0x419: // STM32F42x/STM32F43x
case 0x421: // STM32F446xx
case 0x422: // STM32F30x
case 0x423: // STM32F401x
case 0x431: // STM32F411xE
case 0x429: // STM32L
case 0x432: // STM32F37x
case 0x433: // STM32F401x
case 0x434: // STM32F469/STM32F479
case 0x435: // STM32L4x2/STM32L4x3
case 0x438: // STM32F334
case 0x436: // STM32L
case 0x439: // STM32F30x
case 0x441: // STM32F412
case 0x446: // STM32F303
case 0x449: // STM32F75x/STM32F74x
case 0x451: // STM32F76x/STM32F77x
case 0x452: // STM32F72x/STM32F73x
case 0x458: // STM32F410x
case 0x461: // STM32L496/STM32L9A6
case 0x462: // STM32L451/STM32L452/STM32L462
case 0x463: // STM32F413
case 0x464: // STM32L412/STM32L422
case 0x468: // STM32G4
case 0x469: // STM32G4
case 0x470: // STM32L4R/STM32L4S
case 0x471: // STM32L4P5/STM32L4Q5
case 0x479: // STM32G4
TargetInterface.pokeWord(0xE0042004, 1<<2|1<<1|1<<0); // enable low-power mode debugging
TargetInterface.pokeWord(0xE0042008, 1<<12|1<<11); // turn off WWDG and IWDG in debug mode
break;
case 0x495: // STM32WB55xx/STM32WB35xx
TargetInterface.pokeWord(0xE0042004, 1<<2|1<<1|1<<0); // enable low-power mode debugging
TargetInterface.pokeWord(0xE004203C, 1<<12|1<<11); // turn off WWDG and IWDG in debug mode
break;
case 0x497: // STM32WL5x/STM32WLEx
TargetInterface.pokeWord(0xE0042004, 1<<2|1<<1|1<<0); // enable low-power mode debugging
TargetInterface.pokeWord(0xE004203C, 1<<12|1<<11); // turn off WWDG and IWDG in debug mode
break;
default:
switch ((TargetInterface.peekWord(0x5C001000) & 0xfff))
{
case 0x450:
case 0x480:
TargetInterface.pokeWord(0x5C001004, 1<<2|1<<1|1<<0); // enable low-power mode debugging
TargetInterface.pokeWord(0x5C001034, 1<<6); // turn off WWDG1 in debug mode
break;
default:
TargetInterface.pokeWord(0xE0042004, 1<<8|1<<9|1<<2|1<<1|1<<0); // turn off WWDG and IWDG in debug mode and enable low-power mode debugging
break;
}
}
}
}
function SRAMReset()
{
if (TargetInterface.implementation() == "j-link" || TargetInterface.implementation() == "crossworks_simulator")
TargetInterface.resetAndStop(100);
else
Reset();
}
function FLASHReset()
{
if (TargetInterface.implementation() == "j-link" || TargetInterface.implementation() == "crossworks_simulator")
TargetInterface.resetAndStop(100);
else
Reset();
}
function GetPartName()
{
var CPUID = TargetInterface.peekWord(0xE000ED00);
if (((CPUID>>4)&0xf)==0) // Cortex-M0
switch ((TargetInterface.peekWord(0x40015800) & 0xfff))
{
case 0x457:
case 0x425:
case 0x417:
case 0x447:
return "STM32L0x1/STM32L0x2/STM32L0x3";
case 0x440:
return "STM32F05x/STM32F030x8";
case 0x442:
return "STM32F09x/STM32F030xC";
case 0x444:
return "STM32F03x/STM32F030x4/STM32F030x6";
case 0x445:
return "STM32F04x/STM32F070x6";
case 0x448:
return "STM32F07x/STM32F070xB";
case 0x456:
return "STM32G050xx/STM32G051xx/STM32G061xx";
case 0x460:
return "STM32G070xx/STM32G071xx/STM32G081xx";
case 0x466:
return "STM32G030xx/STM32G031xx/STM32G041xx";
case 0x467:
return "STM32G0B0xx/STM32G0B1xx/STM32G0C1xx";
default: // The ROM table may not be visible
TargetInterface.setDebugInterfaceProperty("component_base", 0xe000e000);
TargetInterface.setDebugInterfaceProperty("component_base", 0xe0001000);
TargetInterface.setDebugInterfaceProperty("component_base", 0xe0002000);
break;
}
else if (((CPUID>>4)&0xfff)==0xD21) // Cortex-M33
switch ((TargetInterface.peekWord(0xE0044000) & 0xfff))
{
case 0x472:
return "STM32L552xx/STM32L562xx";
case 0x482:
return "STM32U575xx/STM32U585xx";
}
else
switch ((TargetInterface.peekWord(0xE0042000) & 0xfff))
{
case 0x420: // low and medium density value
return "STM32F100x4/STM32F100x6/STM32F100x8/STM32F100xB";
case 0x428: // high density value
return "STM32F100xC/STM32F100xD/STM32F100xE";
case 0x412: // low density
return "STM32F10xx4/STM32F10xx6";
case 0x410: // medium density
return "STM32F10xx8/STM32F10xxB";
case 0x414: // high density
return "STM32F10xxC/STM32F10xxD/STM32F10xxE";
case 0x430: // xl density
return "STM32F10xxF/STM32F10xxG";
case 0x418: // connectivity
return "STM32F105xx/STM32F107xx";
case 0x411: // STM32F2xx/STM32F4xx
if ((TargetInterface.peekWord(0xE000ED00) & 0xf0)==0x40)
return "STM32F40x/STM32F41x";
else
return "STM32F205xx/STM32F207xx/STM32F215xx/STM32F217xx";
case 0x413: // STM32F40x/STM32F41x
return "STM32F40x/STM32F41x";
case 0x415: // STM32L4x1/STM32L4x5/STM32L4x6
return "STM32L4x1/STM32L4x5/STM32L4x6";
case 0x416: // low and medium density STM32L
case 0x429:
return "STM32L151x8/STM32L151xB/STM32L152x8/STM32L152xB/STM32L100x6/STM32L100x8/STM32L100xB";
case 0x419: // STM32F42x/STM32F43x
return "STM32F42x/STM32F43x";
case 0x421:
return "STM32F446xx";
case 0x423: // STM32F401
case 0x433: // STM32F401
return "STM32F401x";
case 0x431: // STM32F411xE
return "STM32F411x";
case 0x427: // medium+
case 0x436: // high density STM32L
return "STM32L151xC/STM32L151xD/STM32L152xC/STM32L152xD/STM32L162xD/STM32L100xC";
case 0x434: // STM32F469/STM32F479
return "STM32F469/STM32F479";
case 0x435: // STM32L4x2/L4x3
return "STM32L4x2/STM32L431/STM32L433/STM32L443";
case 0x437:
return "STM32L152E";
case 0x422: // STM32F30x
case 0x439: // STM32F30x
return "STM32F30x";
case 0x432: // STM32F37x
return "STM32F37x";
case 0x438: // STM32F334
return "STM32F334xx/STM32F303x6/STM32F303x8/STM32F328";
case 0x441: // STM32F412
return "STM32F412";
case 0x446:
return "STM32F303xD/STM32F303xE/STM32F398xE";
case 0x449:
return "STM32F75x/STM32F74x";
case 0x451:
return "STM32F76x/STM32F77x";
case 0x452: // STM32F72x/STM32F73x
return "STM32F72x/STM32F73x";
case 0x458: // STM32F410
return "STM32F410x";
case 0x461:
return "STM32L496/STM32L4A6";
case 0x462:
return "STM32L451/STM32L452/STM32L462";
case 0x463:
return "STM32F413";
case 0x464:
return "STM32L412/STM32L422";
case 0x468: // STM32G4 Category 2
return "STM32G431/STM32G441";
case 0x469: // STM32G4 Category 3
return "STM32G471/STM32G473/STM32G474/STM32G483/STM32G484";
case 0x470:
return "STM32L4R/STM32L4S";
case 0x471:
return "STM32L4P5/STM32L4Q5";
case 0x479: // STM32G4 Category 4
return "STM32G491/STM32G4A1";
case 0x495:
return "STM32WB55xx/STM32WB35xx";
case 0x497:
return "STM32WL5x/STM32WLEx";
default:
switch ((TargetInterface.peekWord(0x5C001000) & 0xfff))
{
case 0x450:
if (((CPUID>>4)&0xf)==4)
return "STM32H7_CM4";
else
return "STM32H7";
case 0x480:
return "STM32H7A3/STM32H7B3/STM32H7B0";
}
}
// STM32W108 has a bootloader program in the fixed flash memory area check that it's value is within SRAM
var FIB0 = TargetInterface.peekWord(0x08040000);
if (FIB0 >= 0x20000000 && FIB0 <= 0x20002000)
return "STM32W108";
}
function MatchPartName(name)
{
var family = name.substring(0, 9); // STM32F100, STM32F102, STM32F101, STM32F103, STM32F105, STM32F107, STM32F205, STM32F207, STM32F405, STM32F407, STM32L151, STM32L152, STM32F051, STM32F050, STM32F427, STM32F437
var density = name.substring(10, 11); // 4==16K, 6==32K, 8==64K, B=128K, C=256K, D=384K, E=512K, F=768K, G=1024K, I=2048K
var CPUID = TargetInterface.peekWord(0xE000ED00);
if (((CPUID>>4)&0xf)==0) // Cortex-M0
switch ((TargetInterface.peekWord(0x40015800) & 0xfff))
{
case 0x457:
case 0x425:
case 0x417:
case 0x447:
return (family=="STM32L010") || (family=="STM32L011") || (family=="STM32L031") || (family=="STM32L041") || (family=="STM32L051") || (family=="STM32L052") || (family=="STM32L053") || (family=="STM32L061") || (family=="STM32L062") || (family=="STM32L063") || (family=="STM32L071") || (family=="STM32L072") || (family=="STM32L073") || (family=="STM32L083");
case 0x440:
return (family=="STM32F058") || (family=="STM32F051") || ((family=="STM32F030") && (density=="8"));
case 0x442:
return (family=="STM32F091") || (family=="STM32F098") || ((family=="STM32F030") && (density=="C"));
case 0x444:
return (family=="STM32F031") || (family=="STM32F038") || ((family=="STM32F030") && (density=="4" || density=="6"));
case 0x445:
return (family=="STM32F042") || (family=="STM32F048") || ((family=="STM32F070") && (density=="6"));
case 0x448:
return (family=="STM32F070") || (family=="STM32F071") || (family=="STM32F072") || (family=="STM32F078") || ((family=="STM32F070") && (density=="B"));
case 0x456:
return (family=="STM32G050") || (family=="STM32G051") || (family=="STM32F061");
case 0x460:
return (family=="STM32G070") || (family=="STM32G071") || (family=="STM32F081");
case 0x466:
return (family=="STM32G030") || (family=="STM32G031") || (family=="STM32F041");
case 0x467:
return (family=="STM32G0B0") || (family=="STM32G0B1") || (family=="STM32F0C1");
}
else if (((CPUID>>4)&0xfff)==0xD21) // Cortex-M33
switch ((TargetInterface.peekWord(0xE0044000) & 0xfff))
{
case 0x472:
return (family == "STM32L552") || (family == "STM32L562");
case 0x482:
return (family == "STM32U575") || (family == "STM32U585");
}
else
switch ((TargetInterface.peekWord(0xE0042000) & 0xfff))
{
case 0x420: // low and medium density value
return (family=="STM32F100") && (density=="4" || density=="6" || density=="8" || density=="B");
case 0x428: // high density value
return (family=="STM32F100") && (density=="C" || density=="D" || density=="E");
case 0x412: // low density
return (family=="STM32F101" || family=="STM32F102" || family=="STM32F103") && (density=="4" || density=="6");
case 0x410: // medium density
return (family=="STM32F101" || family=="STM32F102" || family=="STM32F103") && (density =="8" || density=="B");
case 0x414: // high density
return (family=="STM32F101" || family=="STM32F102" || family=="STM32F103") && (density =="C" || density=="D" || density=="E");
case 0x430: // xl density
return (family=="STM32F101" || family=="STM32F103") && (density =="F" || density=="G");
case 0x418: // connectivity
return (family=="STM32F105" || family=="STM32F107");
case 0x411: // STM32F2xx/F4xx
return (family=="STM32F205" || family=="STM32F207" || family=="STM32F215" || family=="STM32F217" || family == "STM32F405" || family == "STM32F407" || family == "STM32F415" || family == "STM32F417");
case 0x413: // STM32F4xx
return (family == "STM32F405" || family == "STM32F407" || family == "STM32F415" || family == "STM32F417");
case 0x415: // STM32L4x6
return (family == "STM32L476" || family == "STM32L486" || family == "STM32L471" || family == "STM32L475");
case 0x416: // low and medium density STM32L
case 0x429:
return (family=="STM32L151" || family=="STM32L152" || family=="STM32L100") && (density=="6" || density=="8" || density=="B");
case 0x419: // STM32F427x/STM32F437x
return (family=="STM32F427" || family=="STM32F437" || family=="STM32F429" || family=="STM32F439") && (density=="G" || density=="I");
case 0x421:
return (family=="STM32F446")
case 0x427: // medium+ density STM32L
case 0x436: // high density STM32L
return (family=="STM32L151" || family=="STM32L152" || family=="STM32L162" || family=="STM32L100") && (density=="C" || density=="D");
case 0x437: // STM32L152E
return (family=="STM32L152") && (density=="E");
case 0x422: // STM32F30x
case 0x439: // STM32F30x
return (family=="STM32F302" || family=="STM32F303");
case 0x423: // STM32F401
case 0x433: // STM32F401
return (family=="STM32F401");
case 0x435:
return (family=="STM32L431" || family=="STM32L432" || family=="STM32L433" || family=="STM32L442" || family=="STM32L443");
case 0x431: // STM32F411xE
return (family=="STM32F411");
case 0x432: // STM32F37x
return (family=="STM32F372" || family=="STM32F373");
case 0x434: // STM32F469/STM32F479
return (family=="STM32F469" || family=="STM32F479");
case 0x438: // STM32F334
return (family=="STM32F334" || family=="STM32F303" || family=="STM32F328");
case 0x441: // STM32F412
return (family=="STM32F412");
case 0x446:
return (family=="STM32F303" || family=="STM32F398");
case 0x449: // STM32F75x/STM32F74x
return (family=="STM32F745" || family=="STM32F746" || family=="STM32F756");
case 0x451: // STM32F76x/STM32F77x
return (family=="STM32F765" || family=="STM32F767" || family=="STM32F769" || family=="STM32F777" || family=="STM32F778" || family=="STM32F779");
case 0x452: // STM32F72x/STM32F73x
return (family=="STM32F722" || family=="STM32F723" || family=="STM32F732" || family=="STM32F733");
case 0x458: // STM32F410x
return (family=="STM32F410");
case 0x461:
return (family=="STM32L496" || family=="STM32L4A6");
case 0x462:
return (family=="STM32L451" || family=="STM32L452" || family == "STM32L462");
case 0x463:
return (family=="STM32F413");
case 0x464:
return (family=="STM32L412" || family=="STM32L422");
case 0x468: // STM32G4 Category 2
return (family=="STM32G431" || family=="STM32G441") && (density=="6" || density=="8" || density=="B");
case 0x469: // STM32G4 Category 3
return (family=="STM32G471" || family=="STM32G473" || family=="STM32G474" || family=="STM32G483" || family=="STM32G484") && (density=="B" || density=="C" || density=="E");
case 0x470:
return (family=="STM32L4R5" || family=="STM32L4R7" || family=="STM32L4R9" || family=="STM32L4S5" || family=="STM32L4S7" || family=="STM32L4S9");
case 0x471:
return (family=="STM32L4P5" || family=="STM32L4Q5");
case 0x479: // STM32G4 Category 4
return (family=="STM32G491" || family=="STM32G4A1") && (density=="E");
case 0x495:
return (family=="STM32WB55" || family=="STM32WB35");
case 0x497:
return (family=="STM32WL55" || family=="STM32WL54" || family=="STM32WLE5" || family=="STM32WLE4");
default:
switch ((TargetInterface.peekWord(0x5C001000) & 0xfff))
{
case 0x450:
return (family.indexOf("STM32H74")==0 || family.indexOf("STM32H75")==0);
case 0x480:
return (family.indexOf("STM32H7A")==0 || family.indexOf("STM32H7B")==0);
}
}
var FIB0 = TargetInterface.peekWord(0x08040000);
if (FIB0 >= 0x20000000 && FIB0 <= 0x20002000)
return family=="STM32W108";
return false;
}
//
// STM32F1xx option byte support
//
var FLASH_KEYR=0x40022004;
var FLASH_OPTKEYR=0x40022008;
var FLASH_SR=0x4002200C;
var FLASH_CR=0x40022010;
//
// Note this function will erase the RDP byte i.e. turn on read protection.
// Call STM32F_Unprotect() to turn off read protection after this has been called.
//
function STM32F_EraseOptionBytes()
{
if (!TargetInterface.isStopped())
TargetInterface.stopAndReset(400);
// unlock FPEC
TargetInterface.pokeWord(FLASH_KEYR, 0x45670123);
TargetInterface.pokeWord(FLASH_KEYR, 0xCDEF89AB);
// unlock OPTWRE
TargetInterface.pokeWord(FLASH_OPTKEYR, 0x45670123);
TargetInterface.pokeWord(FLASH_OPTKEYR, 0xCDEF89AB);
// Erase option bytes
var cr = TargetInterface.peekWord(FLASH_CR);
cr |= (1<<5); // OPTER
TargetInterface.pokeWord(FLASH_CR, cr);
cr |= (1<<6); // STRT
TargetInterface.pokeWord(FLASH_CR, cr);
while (TargetInterface.peekWord(FLASH_SR) & 1);
cr &= ~(1<<5); // ~OPTER
TargetInterface.pokeWord(FLASH_CR, cr);
}
//
// Set the option byte at address to value
// STM32F_EraseOptionBytes() should been called before calling this function.
//
function STM32F_SetOptionByte(address, value)
{
var cr = TargetInterface.peekWord(FLASH_CR);
cr |= (1<<4); // OPTPG
TargetInterface.pokeWord(FLASH_CR, cr);
TargetInterface.pokeUint16(address, value);
while (TargetInterface.peekWord(FLASH_SR) & 1);
cr &= ~(1<<4); // ~FLASH_OPTPG
TargetInterface.pokeWord(FLASH_CR, cr);
}
//
// Turn off read protection
//
function STM32F_Unprotect()
{
STM32F_SetOptionByte(0x1FFFF800, 0xA5);
}
//
// Set user byte
//
function STM32F_SetUSER(b)
{
STM32F_SetOptionByte(0x1FFFF802, b);
}
//
// Set user data0
//
function STM32F_SetData0(b)
{
STM32F_SetOptionByte(0x1FFFF804, b);
}
//
// Set user data1
//
function STM32F_SetData1(b)
{
STM32F_SetOptionByte(0x1FFFF806, b);
}
//
// STM32L option byte support
//
var FLASH2_PECR=0x40023C04;
var FLASH2_PEKEYR=0x40023C0C;
var FLASH2_OPTKEYR=0x40023C14;
var FLASH2_SR=0x40023C18;
function STM32L_SetOptionByte(address, value)
{
if (!TargetInterface.isStopped())
TargetInterface.stopAndReset(400);
// Unlock PECR
TargetInterface.pokeWord(FLASH2_PEKEYR, 0x89ABCDEF);
TargetInterface.pokeWord(FLASH2_PEKEYR, 0x02030405);
// Unlock option byte block
TargetInterface.pokeWord(FLASH2_OPTKEYR, 0xFBEAD9C8);
TargetInterface.pokeWord(FLASH2_OPTKEYR, 0x24252627);
// Erase/Write option byte word
var pecr = TargetInterface.peekWord(FLASH2_PECR);
pecr |= (1<<8); // FTDW
TargetInterface.pokeWord(FLASH2_PECR, pecr);
TargetInterface.pokeWord(address, value);
while (TargetInterface.peekWord(FLASH2_SR) & 1);
pecr &= ~(1<<8); // ~FTDW
TargetInterface.pokeWord(FLASH2_PECR, pecr);
}
function STM32L_MakeOptionWord(b0, b1)
{
return (b0|b1<<8|((~b0)&0xff)<<16|((~b1)&0xff)<<24);
}
function STM32L_SetUSER(u)
{
STM32L_SetOptionByte(0x1FF80004, STM32L_MakeOptionWord(u, 0));
}
//
// STM32F2xx option byte support
//
var FLASH3_KEYR=0x40023C04;
var FLASH3_OPTKEYR=0x40023C08;
var FLASH3_SR=0x40023C0C;
var FLASH3_CR=0x40023C10;
var FLASH3_OPTCR=0x40023C14;
//
// Set the USER option byte
//
function STM32F2xx_SetUSER(value)
{
if (!TargetInterface.isStopped())
TargetInterface.stopAndReset(400);
// unlock OPTCR
TargetInterface.pokeWord(FLASH3_OPTKEYR, 0x08192A3B);
TargetInterface.pokeWord(FLASH3_OPTKEYR, 0x4C5D6E7F);
// write USER option byte and then the OPTSTRT bit
TargetInterface.pokeByte(FLASH3_OPTCR, value & 0xFC);
TargetInterface.pokeByte(FLASH3_OPTCR, (value & 0xFC) | 2);
// wait
while (TargetInterface.peekWord(FLASH3_SR) & (1<<16));
}