qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

isp_flashing_guide.md (21408B)


      1 # ISP Flashing Guide
      2 
      3 In order to flash a microcontroller over USB, it needs something called a bootloader. This bootloader lives in a specific section of the flash memory, and allows you to load the actual application firmware (in this case, QMK) into the rest of the flash.
      4 
      5 However, it can sometimes happen that the bootloader becomes corrupted and needs reflashing, or you may want to change the bootloader to another one. It's not possible to do this with the existing bootloader, because, of course, it is already running, and cannot overwrite itself. Instead, you will need to ISP flash the microcontroller.
      6 
      7 There are several different kinds of bootloaders available for AVR microcontrollers. Most STM32 ARM-based microcontrollers already have a USB-capable bootloader in ROM, so generally do not need to be ISP flashed. The one current exception is the [STM32F103](#flashing-stm32duino-bootloader).
      8 
      9 ## Hardware
     10 
     11 One of the following devices is required to perform the ISP flashing. The product links are to the official versions, however you can certainly source them elsewhere.
     12 
     13 You'll also need some jumper wires to connect the ISP flasher and the target board. Some boards have an ISP header with the necessary pins broken out. If not, then you will need to temporarily solder the wires to the PCB -- usually to switch pins or directly to the MCU.
     14 The wiring is fairly straightforward; for the most part, you'll be connecting like to like. Refer to the target MCU's datasheet for the exact `RESET`, `SCLK`, `MOSI` and `MISO` pins.
     15 
     16 ### Pro Micro as ISP
     17 
     18 [SparkFun Pro Micro](https://www.sparkfun.com/products/12640)
     19 
     20 To use a 5V/16MHz Pro Micro as an ISP flashing tool, you will first need to load a [special firmware](https://github.com/qmk/qmk_firmware/blob/master/util/pro_micro_ISP_B6_10.hex) onto it that emulates a hardware ISP flasher.
     21 
     22 **AVRDUDE Programmer**: `avrisp`  
     23 **AVRDUDE Port**: Serial
     24 
     25 #### Wiring
     26 
     27 |Pro Micro  |Keyboard|
     28 |-----------|--------|
     29 |`VCC`      |`VCC`   |
     30 |`GND`      |`GND`   |
     31 |`10` (`B6`)|`RESET` |
     32 |`15` (`B1`)|`SCLK`  |
     33 |`16` (`B2`)|`MOSI`  |
     34 |`14` (`B3`)|`MISO`  |
     35 
     36 ::: warning
     37 Note that the `10` pin on the Pro Micro should be wired to the `RESET` pin on the keyboard's controller. ***DO NOT*** connect the `RESET` pin on the Pro Micro to the `RESET` on the keyboard.
     38 :::
     39 
     40 
     41 ### Arduino Uno / Micro as ISP
     42 
     43 [Arduino Uno](https://store.arduino.cc/products/arduino-uno-rev3)
     44 [Arduino Micro](https://store.arduino.cc/products/arduino-micro)
     45 
     46 A standard Uno or Micro can be used as an ISP flashing tool using the [example "ArduinoISP" sketch](https://docs.arduino.cc/built-in-examples/arduino-isp/ArduinoISP#load-the-sketch) to emulate an STK500 ISP. Also works with Sparkfun Pro Micros and clones.
     47 
     48 **AVRDUDE Programmer**: `stk500v1`  
     49 **AVRDUDE Port**: Serial
     50 
     51 #### Wiring
     52 
     53 |Uno        |Keyboard|
     54 |-----------|--------|
     55 |`5V`       |`VCC`   |
     56 |`GND`      |`GND`   |
     57 |`10` (`B2`)|`RESET` |
     58 |`13` (`B5`)|`SCLK`  |
     59 |`11` (`B3`)|`MOSI`  |
     60 |`12` (`B4`)|`MISO`  |
     61 
     62 |Micro      |Keyboard|
     63 |-----------|--------|
     64 |`5V`       |`VCC`   |
     65 |`GND`      |`GND`   |
     66 |`10` (`B6`)|`RESET` |
     67 |`15` (`B1`)|`SCLK`  |
     68 |`16` (`B2`)|`MOSI`  |
     69 |`14` (`B3`)|`MISO`  |
     70 
     71 ::: warning
     72 Note that the `10` pin on the Uno/Micro should be wired to the `RESET` pin on the keyboard's controller. ***DO NOT*** connect the `RESET` pin on the Uno/Micro to the `RESET` on the keyboard.
     73 :::
     74 
     75 
     76 ### Teensy 2.0 as ISP
     77 
     78 [PJRC Teensy 2.0](https://www.pjrc.com/store/teensy.html)
     79 
     80 To use a Teensy 2.0 as an ISP flashing tool, you will first need to load a [special firmware](https://github.com/qmk/qmk_firmware/blob/master/util/teensy_2.0_ISP_B0.hex) onto it that emulates a hardware ISP flasher.
     81 
     82 **AVRDUDE Programmer**: `avrisp`  
     83 **AVRDUDE Port**: Serial
     84 
     85 #### Wiring
     86 
     87 |Teensy|Keyboard|
     88 |------|--------|
     89 |`VCC` |`VCC`   |
     90 |`GND` |`GND`   |
     91 |`B0`  |`RESET` |
     92 |`B1`  |`SCLK`  |
     93 |`B2`  |`MOSI`  |
     94 |`B3`  |`MISO`  |
     95 
     96 ::: warning
     97 Note that the `B0` pin on the Teensy should be wired to the `RESET` pin on the keyboard's controller. ***DO NOT*** connect the `RESET` pin on the Teensy to the `RESET` on the keyboard.
     98 :::
     99 
    100 
    101 ### SparkFun PocketAVR / USBtinyISP
    102 
    103 [SparkFun PocketAVR](https://www.sparkfun.com/products/9825)  
    104 [Adafruit USBtinyISP](https://www.adafruit.com/product/46)  
    105 
    106 ::: warning
    107 SparkFun PocketAVR and USBtinyISP **DO NOT support** AVR chips with more than 64 KiB of flash (e.g., the AT90USB128 series). This limitation is mentioned on the [shop page for SparkFun PocketAVR](https://www.sparkfun.com/products/9825) and in the [FAQ for USBtinyISP](https://learn.adafruit.com/usbtinyisp/f-a-q#faq-2270879). If you try to use one of these programmers with AT90USB128 chips, you will get verification errors from `avrdude`, and the bootloader won't be flashed properly (e.g., see the [issue #3286](https://github.com/qmk/qmk_firmware/issues/3286)).
    108 :::
    109 
    110 **AVRDUDE Programmer**: `usbtiny`  
    111 **AVRDUDE Port**: `usb`
    112 
    113 #### Wiring
    114 
    115 |ISP      |Keyboard|
    116 |---------|--------|
    117 |`VCC`    |`VCC`   |
    118 |`GND`    |`GND`   |
    119 |`RST`    |`RESET` |
    120 |`SCLK`   |`SCLK`  |
    121 |`MOSI`   |`MOSI`  |
    122 |`MISO`   |`MISO`  |
    123 
    124 
    125 ### USBasp
    126 
    127 [Thomas Fischl's USBasp](https://www.fischl.de/usbasp/)
    128 
    129 **AVRDUDE Programmer**: `usbasp`  
    130 **AVRDUDE Port**: `usb`
    131 
    132 #### Wiring
    133 
    134 |ISP      |Keyboard|
    135 |---------|--------|
    136 |`VCC`    |`VCC`   |
    137 |`GND`    |`GND`   |
    138 |`RST`    |`RESET` |
    139 |`SCLK`   |`SCLK`  |
    140 |`MOSI`   |`MOSI`  |
    141 |`MISO`   |`MISO`  |
    142 
    143 
    144 ### Bus Pirate
    145 
    146 [Adafruit Bus Pirate](https://www.adafruit.com/product/237)
    147 
    148 ::: warning
    149 The 5-pin "ICSP" header is for ISP flashing the PIC microcontroller of the Bus Pirate. Connect your target board to the 10-pin header opposite the USB connector instead.
    150 :::
    151 
    152 **AVRDUDE Programmer**: `buspirate`  
    153 **AVRDUDE Port**: Serial
    154 
    155 #### Wiring
    156 
    157 |Bus Pirate|Keyboard|
    158 |----------|--------|
    159 |`+5V`     |`VCC`   |
    160 |`GND`     |`GND`   |
    161 |`RST`     |`RESET` |
    162 |`CLK`     |`SCLK`  |
    163 |`MOSI`    |`MOSI`  |
    164 |`MISO`    |`MISO`  |
    165 
    166 ## Software
    167 
    168 [QMK Toolbox](https://github.com/qmk/qmk_toolbox/releases) supports flashing both the ISP firmware and bootloader, but note that it cannot (currently) set the AVR fuse bytes for the actual ISP flashing step, so you may want to work with `avrdude` directly instead.
    169 
    170 Setting up the [QMK environment](newbs) is highly recommended, as it automatically installs `avrdude` along with a host of other tools.
    171 
    172 ## Bootloader Firmware
    173 
    174 One of these files is what you will be ISP flashing onto the board. The default fuses are also listed.
    175 
    176 If you're not sure what your board uses, look in the `rules.mk` file for the keyboard in QMK. The `MCU` and `BOOTLOADER` lines will have the values you need. It may differ between different versions of the board.
    177 
    178 ### Atmel DFU
    179 
    180 These are the [factory default bootloaders](https://www.microchip.com/content/dam/mchp/documents/OTH/ProductDocuments/SoftwareLibraries/Firmware/megaUSB_DFU_Bootloaders.zip) shipped by Atmel (now Microchip). Note that the AT90USB64 and AT90USB128 bootloaders are [slightly modified](https://github.com/qmk/qmk_firmware/pull/14064), due to a bug causing them to not enumerate properly in Windows 8 and later.
    181 
    182 |MCU                                                                                               |Low   |High                           |Extended|USB ID     |
    183 |--------------------------------------------------------------------------------------------------|------|-------------------------------|--------|-----------|
    184 |[ATmega16U4](https://github.com/qmk/qmk_firmware/blob/master/util/bootloader_atmega16u4_1.0.1.hex)|`0x5E`|`0x99` / `0xD9` (JTAG disabled)|`0xF3`  |`03EB:2FF3`|
    185 |[ATmega32U4](https://github.com/qmk/qmk_firmware/blob/master/util/bootloader_atmega32u4_1.0.0.hex)|`0x5E`|`0x99` / `0xD9` (JTAG disabled)|`0xF3`  |`03EB:2FF4`|
    186 |[AT90USB64](https://github.com/qmk/qmk_firmware/blob/master/util/bootloader_at90usb64_1.0.0.hex)  |`0x5E`|`0x9B` / `0xDB` (JTAG disabled)|`0xF3`  |`03EB:2FF9`|
    187 |[AT90USB128](https://github.com/qmk/qmk_firmware/blob/master/util/bootloader_at90usb128_1.0.1.hex)|`0x5E`|`0x99` / `0xD9` (JTAG disabled)|`0xF3`  |`03EB:2FFB`|
    188 
    189 ### Caterina
    190 
    191 This is the default Arduino-style bootloader derived from the [LUFA CDC bootloader](https://github.com/abcminiuser/lufa/tree/master/Bootloaders/CDC), and is only for the ATmega32U4.
    192 
    193 There are several variants depending on the vendor, but they all mostly work the same way. The SparkFun variants, for example, require the `RESET` pin to be [grounded twice quickly](https://learn.sparkfun.com/tutorials/pro-micro--fio-v3-hookup-guide#ts-reset) in order to stay in bootloader mode for more than 750 ms.
    194 
    195 |MCU                                                                                                                                                              |Low   |High  |Extended|USB ID     |
    196 |-----------------------------------------------------------------------------------------------------------------------------------------------------------------|------|------|--------|-----------|
    197 |[SparkFun Pro Micro (3V3/8MHz)](https://github.com/sparkfun/Arduino_Boards/blob/master/sparkfun/avr/bootloaders/caterina/Caterina-promicro8.hex)                 |`0xFF`|`0xD8`|`0xFE`  |`1B4F:9203`|
    198 |[SparkFun Pro Micro (5V/16MHz)](https://github.com/sparkfun/Arduino_Boards/blob/master/sparkfun/avr/bootloaders/caterina/Caterina-promicro16.hex)                |`0xFF`|`0xD8`|`0xFB`  |`1B4F:9205`|
    199 |[SparkFun LilyPadUSB (and some Pro Micro clones)](https://github.com/sparkfun/Arduino_Boards/blob/main/sparkfun/avr/bootloaders/caterina/Caterina-lilypadusb.hex)|`0xFF`|`0xD8`|`0xFE`  |`1B4F:9207`|
    200 |[Pololu A-Star 32U4](https://github.com/pololu/a-star/blob/master/bootloaders/caterina/Caterina-A-Star.hex)*                                                     |`0xFF`|`0xD0`|`0xF8`  |`1FFB:0101`|
    201 |[Adafruit Feather 32U4](https://github.com/adafruit/Caterina-Bootloader/blob/master/Built%20Firmwares/Caterina-Feather32u4.hex)                                  |`0xFF`|`0xD8`|`0xFB`  |`239A:000C`|
    202 |[Adafruit ItsyBitsy 32U4 (3V3/8MHz)](https://github.com/adafruit/Caterina-Bootloader/blob/master/Caterina_itsybitsy3V.hex)*                                      |`0xFF`|`0xD8`|`0xFB`  |`239A:000D`|
    203 |[Adafruit ItsyBitsy 32U4 (5V/16MHz)](https://github.com/adafruit/Caterina-Bootloader/blob/master/Caterina_itsybitsy5V.hex)                                       |`0xFF`|`0xD8`|`0xFB`  |`239A:000E`|
    204 |[Arduino Leonardo](https://github.com/arduino/ArduinoCore-avr/blob/master/bootloaders/caterina/Caterina-Leonardo.hex)*                                           |`0xFF`|`0xD8`|`0xFB`  |`2341:0036`|
    205 |[Arduino Micro](https://github.com/arduino/ArduinoCore-avr/blob/master/bootloaders/caterina/Caterina-Micro.hex)*                                                 |`0xFF`|`0xD8`|`0xFB`  |`2341:0037`|
    206 
    207 ::: tip
    208 Files marked with a * have combined Arduino sketches, which runs by default and also appears as a serial port. However, this is *not* the bootloader device.
    209 :::
    210 
    211 ### BootloadHID (PS2AVRGB)
    212 
    213 This bootloader is primarily for keyboards originally designed for the PS2AVRGB firmware and Bootmapper Client. It is not recommended for use in new designs.
    214 
    215 |MCU                                                                                                        |Low   |High  |USB ID     |
    216 |-----------------------------------------------------------------------------------------------------------|------|------|-----------|
    217 |[ATmega32A](https://github.com/qmk/qmk_firmware/blob/master/util/bootloader_ps2avrgb_bootloadhid_1.0.1.hex)|`0x0F`|`0xD0`|`16C0:05DF`|
    218 
    219 ### USBaspLoader
    220 
    221 USBaspLoader is a bootloader based on V-USB that emulates a hardware USBasp device. It runs on ATmega32A and ATmega328P MCUs.
    222 
    223 Precompiled `.hex` files are generally not available, but you can compile it yourself by setting up the QMK environment and cloning the appropriate branch of Coseyfannitutti's USBaspLoader fork:
    224 
    225 |MCU                                                                          |Low   |High  |Extended|USB ID     |
    226 |-----------------------------------------------------------------------------|------|------|--------|-----------|
    227 |[ATmega32A](https://github.com/coseyfannitutti/USBaspLoader/tree/atmega32a)  |`0x1F`|`0xC0`|*n/a*   |`16C0:05DC`|
    228 |[ATmega328P](https://github.com/coseyfannitutti/USBaspLoader/tree/atmega328p)|`0xD7`|`0xD0`|`0x04`  |`16C0:05DC`|
    229 
    230 From there, simply `cd` to the `firmware/` directory and run `make`, which should produce a file called `main.hex`.
    231 
    232 :::tip
    233 Some boards may have their own specialized build of this bootloader in a separate repository. This will usually be linked to in the board's readme.
    234 :::
    235 
    236 ## Flashing the Bootloader
    237 
    238 Open a new Terminal window - if you are on Windows, use MSYS2 or QMK MSYS, not the Command Prompt. Navigate to the directory your bootloader `.hex` is in. Now it's time to run the `avrdude` command.
    239 
    240 The syntax of `avrdude` is:
    241 
    242 ```
    243 avrdude -c <programmer> -P <port> -p <mcu> -U flash:w:<filename>:i
    244 ```
    245 
    246  * `<programmer>` corresponds to the programmer type listed for each ISP flasher in the [Hardware](#hardware) section, for example `avrisp`.
    247  * `<port>` is the serial port that appears when you plug the ISP flasher in, if any. For some programmers this is simply `usb` (or you can omit the `-P` argument completely) since they do not operate as a serial device.
    248    * Windows: `COMx` - check Device Manager, under the "Ports (COM & LPT)" section
    249    * Linux: `/dev/ttyACMx`
    250    * macOS: `/dev/tty.usbmodemXXXXXX`
    251  * `<mcu>` should be the lowercase name of the target AVR microcontroller, for example `atmega32u4`.
    252  * `<filename>` is the absolute or relative path to the bootloader to be flashed, for example `Caterina-Micro.hex`.
    253 
    254 You can also run `man avrdude` for more information.
    255 
    256 If all goes well, you should get output similar to the following:
    257 
    258 ```
    259 avrdude: AVR device initialized and ready to accept instructions
    260 
    261 Reading | ################################################## | 100% 0.00s
    262 
    263 avrdude: Device signature = 0x1e9587 (probably m32u4)
    264 avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
    265          To disable this feature, specify the -D option.
    266 avrdude: erasing chip
    267 avrdude: reading input file "Caterina-Micro.hex"
    268 avrdude: writing flash (32730 bytes):
    269 
    270 Writing | ################################################## | 100% 11.58s
    271 
    272 avrdude: 32730 bytes of flash written
    273 avrdude: verifying flash memory against Caterina-Micro.hex:
    274 avrdude: load data flash data from input file Caterina-Micro.hex:
    275 avrdude: input file Caterina-Micro.hex contains 32730 bytes
    276 avrdude: reading on-chip flash data:
    277 
    278 Reading | ################################################## | 100% 10.33s
    279 
    280 avrdude: verifying ...
    281 avrdude: 32730 bytes of flash verified
    282 
    283 avrdude: safemode: Fuses OK (E:CB, H:D8, L:FF)
    284 
    285 avrdude done.  Thank you.
    286 ```
    287 
    288 ### Setting the Fuses
    289 
    290 This is a slightly more advanced topic, but may be necessary if you are switching from one bootloader to another (for example, Caterina to Atmel/QMK DFU on a Pro Micro). Fuses control some of the low-level functionality of the AVR microcontroller, such as clock speed, whether JTAG is enabled, and the size of the section of flash memory reserved for the bootloader, among other things. You can find a fuse calculator for many AVR parts [here](https://www.engbedded.com/conffuse/).
    291 
    292 ::: warning
    293 Setting incorrect fuse values, in particular the clock-related bits, may render the MCU practically unrecoverable without high voltage programming (not covered here)! Make sure to double check the commands you enter before you execute them.
    294 :::
    295 
    296 To set the fuses, add the following to the `avrdude` command:
    297 
    298 ```
    299 -U lfuse:w:0xXX:m -U hfuse:w:0xXX:m -U efuse:w:0xXX:m
    300 ```
    301 
    302 where the `lfuse`, `hfuse` and `efuse` arguments represent the low, high and extended fuse bytes as listed in the [Hardware](#hardware) section.
    303 
    304 ::: tip
    305 You may get a warning from `avrdude` that the extended fuse byte does not match what you provided when reading it back. If the second hex digit matches, this can usually be safely ignored, because the top four bits of this fuse do not actually exist on many AVR parts, and may read back as anything.
    306 :::
    307 
    308 ## Creating a "Production" Firmware
    309 
    310 For mass production purposes, it is possible to join the bootloader and QMK firmware together into a single file, due to the way the [Intel Hex format](https://en.wikipedia.org/wiki/Intel_HEX) works:
    311 
    312  1. Open the QMK firmware and bootloader `.hex` files in a text editor.
    313  2. Remove the last line of the QMK firmware (which should be `:00000001FF` - this is just an "end of file" marker).
    314  3. Paste the contents of the bootloader `.hex` file onto a new line at the end of the QMK firmware file, with no empty lines between.
    315  4. Save it as a new file, for example `<keyboard>_<keymap>_production.hex`.
    316 
    317 You can then ISP flash this combined firmware instead, which allows you to skip the extra step of flashing the QMK firmware over USB.
    318 
    319 ## Flashing STM32Duino Bootloader
    320 
    321 As mentioned above, *most* supported STM32 devices already possess a USB DFU bootloader which cannot be overwritten, however the ROM bootloader in the STM32F103 used on the Bluepill is not USB capable. In this case an ST-Link V2 dongle is required to upload the STM32Duino bootloader to the device. These can be readily purchased for relatively cheap on eBay and other places.
    322 
    323 This bootloader is a descendant of the Maple bootloader by Leaflabs, and is compatible with dfu-util.
    324 
    325 ### Software
    326 
    327 To communicate with the ST-Link, you must install the following packages:
    328 
    329 * **macOS:** `brew install stlink openocd`
    330 * **Windows (MSYS2):** `pacman -S mingw-w64-x86_64-stlink mingw-w64-x86_64-openocd`
    331 * **Linux:** will vary by distribution, but will likely be `stlink` and `openocd` through your particular package manager
    332 
    333 Additionally, you may need to update the ST-Link's firmware with the [`STSW-LINK007`](https://www.st.com/en/development-tools/stsw-link007.html) application. Note you will be asked to provide your name and email address if you do not have an ST.com account (this does not create one).
    334 
    335 Finally, the bootloader binary itself can be downloaded from [here](https://github.com/rogerclarkmelbourne/STM32duino-bootloader/blob/master/bootloader_only_binaries/generic_boot20_pc13.bin).
    336 
    337 ### Wiring
    338 
    339 Connect the four-pin header on the end of the Bluepill to the matching pins on the ST-Link (the pinout will usually be printed on the side):
    340 
    341 |ST-Link      |Bluepill|
    342 |-------------|--------|
    343 |`GND` (6)    |`GND`   |
    344 |`SWCLK` (2)  |`DCLK`  |
    345 |`SWDIO` (4)  |`DIO`   |
    346 |`3.3V` (8)   |`3.3`   |
    347 
    348 ### Flashing
    349 
    350 Firstly, make sure both jumpers on the Bluepill are set to 0.
    351 
    352 Check that the ST-Link can talk to the Bluepill by running `st-info --probe`:
    353 
    354 ```
    355 Found 1 stlink programmers
    356   version:    V2J37S7
    357   serial:     2C1219002B135937334D4E00
    358   flash:      65536 (pagesize: 1024)
    359   sram:       20480
    360   chipid:     0x0410
    361   descr:      F1xx Medium-density
    362 ```
    363 
    364 If the reported `chipid` is `0x0410`, everything is working. If it is `0x0000`, check your wiring, and try swapping the `SWDIO` and `SWCLK` pins, as some ST-Link dongles may have incorrect pinouts.
    365 
    366 Next, run the following command:
    367 
    368 ```
    369 st-flash --reset --format binary write <path-to-bootloader> 0x08000000
    370 ```
    371 
    372 where `<path-to-bootloader>` is the path to the bootloader `.bin` file above. You can run this command from the directory you downloaded it to, so that you can simply pass in the filename.
    373 
    374 If all goes well, you should get output similar to the following:
    375 
    376 ```
    377 st-flash 1.7.0
    378 2022-03-08T12:16:30 INFO common.c: F1xx Medium-density: 20 KiB SRAM, 64 KiB flash in at least 1 KiB pages.
    379 file generic_boot20_pc13.bin md5 checksum: 333c30605e739ce9bedee5999fdaf81b, stlink checksum: 0x0008e534
    380 2022-03-08T12:16:30 INFO common.c: Attempting to write 7172 (0x1c04) bytes to stm32 address: 134217728 (0x8000000)
    381 2022-03-08T12:16:30 INFO common.c: Flash page at addr: 0x08000000 erased
    382 2022-03-08T12:16:30 INFO common.c: Flash page at addr: 0x08000400 erased
    383 2022-03-08T12:16:31 INFO common.c: Flash page at addr: 0x08000800 erased
    384 2022-03-08T12:16:31 INFO common.c: Flash page at addr: 0x08000c00 erased
    385 2022-03-08T12:16:31 INFO common.c: Flash page at addr: 0x08001000 erased
    386 2022-03-08T12:16:31 INFO common.c: Flash page at addr: 0x08001400 erased
    387 2022-03-08T12:16:31 INFO common.c: Flash page at addr: 0x08001800 erased
    388 2022-03-08T12:16:31 INFO common.c: Flash page at addr: 0x08001c00 erased
    389 2022-03-08T12:16:31 INFO common.c: Finished erasing 8 pages of 1024 (0x400) bytes
    390 2022-03-08T12:16:31 INFO common.c: Starting Flash write for VL/F0/F3/F1_XL
    391 2022-03-08T12:16:31 INFO flash_loader.c: Successfully loaded flash loader in sram
    392 2022-03-08T12:16:31 INFO flash_loader.c: Clear DFSR
    393   8/  8 pages written
    394 2022-03-08T12:16:31 INFO common.c: Starting verification of write complete
    395 2022-03-08T12:16:31 INFO common.c: Flash written and verified! jolly good!
    396 2022-03-08T12:16:31 WARN common.c: NRST is not connected
    397 ```
    398 
    399 Otherwise, if you receive an `Unknown memory region` error, run the following command to unlock the STM32F103:
    400 
    401 ```
    402 openocd -f interface/stlink.cfg -f target/stm32f1x.cfg -c "init; reset halt; stm32f1x unlock 0; reset halt; exit"
    403 ```
    404 
    405 Then re-plug the ST-Link and try again.
    406 
    407 After all of this, unplug the Bluepill from the ST-Link and connect it to USB. It should now be ready to flash using dfu-util, the QMK CLI or Toolbox.