Refactor bootloader_jump() implementations (#15450)
				
					
				
			* Refactor `bootloader_jump()` implementations * Fix tests? * Rename `atmel-samba` to `md-boot`
This commit is contained in:
		
							parent
							
								
									cffe143ca2
								
							
						
					
					
						commit
						6bc870d899
					
				
					 32 changed files with 701 additions and 493 deletions
				
			
		| 
						 | 
				
			
			@ -43,6 +43,7 @@ all: elf
 | 
			
		|||
VPATH += $(COMMON_VPATH)
 | 
			
		||||
PLATFORM:=TEST
 | 
			
		||||
PLATFORM_KEY:=test
 | 
			
		||||
BOOTLOADER_TYPE:=none
 | 
			
		||||
 | 
			
		||||
ifeq ($(strip $(DEBUG)), 1)
 | 
			
		||||
CONSOLE_ENABLE = yes
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@
 | 
			
		|||
#     bootloadhid  HIDBootFlash compatible (ATmega32A)
 | 
			
		||||
#     usbasploader USBaspLoader (ATmega328P)
 | 
			
		||||
# ARM:
 | 
			
		||||
#     halfkay      PJRC Teensy
 | 
			
		||||
#     kiibohd      Input:Club Kiibohd bootloader (only used on their boards)
 | 
			
		||||
#     stm32duino   STM32Duino (STM32F103x8)
 | 
			
		||||
#     stm32-dfu    STM32 USB DFU in ROM
 | 
			
		||||
| 
						 | 
				
			
			@ -43,6 +44,8 @@
 | 
			
		|||
ifeq ($(strip $(BOOTLOADER)), atmel-dfu)
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_ATMEL_DFU
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_DFU
 | 
			
		||||
    BOOTLOADER_TYPE = dfu
 | 
			
		||||
 | 
			
		||||
    ifneq (,$(filter $(MCU), at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))
 | 
			
		||||
        BOOTLOADER_SIZE = 4096
 | 
			
		||||
    endif
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +56,8 @@ endif
 | 
			
		|||
ifeq ($(strip $(BOOTLOADER)), lufa-dfu)
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_LUFA_DFU
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_DFU
 | 
			
		||||
    BOOTLOADER_TYPE = dfu
 | 
			
		||||
 | 
			
		||||
    ifneq (,$(filter $(MCU), at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))
 | 
			
		||||
        BOOTLOADER_SIZE ?= 4096
 | 
			
		||||
    endif
 | 
			
		||||
| 
						 | 
				
			
			@ -63,6 +68,8 @@ endif
 | 
			
		|||
ifeq ($(strip $(BOOTLOADER)), qmk-dfu)
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_QMK_DFU
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_DFU
 | 
			
		||||
    BOOTLOADER_TYPE = dfu
 | 
			
		||||
 | 
			
		||||
    ifneq (,$(filter $(MCU), at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))
 | 
			
		||||
        BOOTLOADER_SIZE ?= 4096
 | 
			
		||||
    endif
 | 
			
		||||
| 
						 | 
				
			
			@ -73,10 +80,14 @@ endif
 | 
			
		|||
ifeq ($(strip $(BOOTLOADER)), qmk-hid)
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_QMK_HID
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_HID
 | 
			
		||||
    BOOTLOADER_TYPE = dfu
 | 
			
		||||
 | 
			
		||||
    BOOTLOADER_SIZE ?= 4096
 | 
			
		||||
endif
 | 
			
		||||
ifeq ($(strip $(BOOTLOADER)), halfkay)
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_HALFKAY
 | 
			
		||||
    BOOTLOADER_TYPE = halfkay
 | 
			
		||||
 | 
			
		||||
    ifeq ($(strip $(MCU)), atmega32u4)
 | 
			
		||||
        BOOTLOADER_SIZE = 512
 | 
			
		||||
    endif
 | 
			
		||||
| 
						 | 
				
			
			@ -86,18 +97,26 @@ ifeq ($(strip $(BOOTLOADER)), halfkay)
 | 
			
		|||
endif
 | 
			
		||||
ifeq ($(strip $(BOOTLOADER)), caterina)
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_CATERINA
 | 
			
		||||
    BOOTLOADER_TYPE = caterina
 | 
			
		||||
 | 
			
		||||
    BOOTLOADER_SIZE = 4096
 | 
			
		||||
endif
 | 
			
		||||
ifneq (,$(filter $(BOOTLOADER), bootloadhid bootloadHID))
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_BOOTLOADHID
 | 
			
		||||
    BOOTLOADER_TYPE = bootloadhid
 | 
			
		||||
 | 
			
		||||
    BOOTLOADER_SIZE = 4096
 | 
			
		||||
endif
 | 
			
		||||
ifneq (,$(filter $(BOOTLOADER), usbasploader USBasp))
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_USBASP
 | 
			
		||||
    BOOTLOADER_TYPE = usbasploader
 | 
			
		||||
 | 
			
		||||
    BOOTLOADER_SIZE = 4096
 | 
			
		||||
endif
 | 
			
		||||
ifeq ($(strip $(BOOTLOADER)), lufa-ms)
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_MS
 | 
			
		||||
    BOOTLOADER_TYPE = dfu
 | 
			
		||||
 | 
			
		||||
    BOOTLOADER_SIZE ?= 8192
 | 
			
		||||
    FIRMWARE_FORMAT = bin
 | 
			
		||||
cpfirmware: lufa_warning
 | 
			
		||||
| 
						 | 
				
			
			@ -115,6 +134,7 @@ endif
 | 
			
		|||
 | 
			
		||||
ifeq ($(strip $(BOOTLOADER)), stm32-dfu)
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_STM32_DFU
 | 
			
		||||
    BOOTLOADER_TYPE = stm32_dfu
 | 
			
		||||
 | 
			
		||||
    # Options to pass to dfu-util when flashing
 | 
			
		||||
    DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
 | 
			
		||||
| 
						 | 
				
			
			@ -122,6 +142,7 @@ ifeq ($(strip $(BOOTLOADER)), stm32-dfu)
 | 
			
		|||
endif
 | 
			
		||||
ifeq ($(strip $(BOOTLOADER)), apm32-dfu)
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_APM32_DFU
 | 
			
		||||
    BOOTLOADER_TYPE = stm32_dfu
 | 
			
		||||
 | 
			
		||||
    # Options to pass to dfu-util when flashing
 | 
			
		||||
    DFU_ARGS ?= -d 314B:0106 -a 0 -s 0x08000000:leave
 | 
			
		||||
| 
						 | 
				
			
			@ -129,6 +150,7 @@ ifeq ($(strip $(BOOTLOADER)), apm32-dfu)
 | 
			
		|||
endif
 | 
			
		||||
ifeq ($(strip $(BOOTLOADER)), gd32v-dfu)
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_GD32V_DFU
 | 
			
		||||
    BOOTLOADER_TYPE = gd32v_dfu
 | 
			
		||||
 | 
			
		||||
    # Options to pass to dfu-util when flashing
 | 
			
		||||
    DFU_ARGS ?= -d 28E9:0189 -a 0 -s 0x08000000:leave
 | 
			
		||||
| 
						 | 
				
			
			@ -136,6 +158,8 @@ ifeq ($(strip $(BOOTLOADER)), gd32v-dfu)
 | 
			
		|||
endif
 | 
			
		||||
ifeq ($(strip $(BOOTLOADER)), kiibohd)
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_KIIBOHD
 | 
			
		||||
    BOOTLOADER_TYPE = kiibohd
 | 
			
		||||
 | 
			
		||||
    ifeq ($(strip $(MCU_ORIG)), MK20DX128)
 | 
			
		||||
        MCU_LDSCRIPT = MK20DX128BLDR4
 | 
			
		||||
    endif
 | 
			
		||||
| 
						 | 
				
			
			@ -151,8 +175,7 @@ ifeq ($(strip $(BOOTLOADER)), stm32duino)
 | 
			
		|||
    OPT_DEFS += -DBOOTLOADER_STM32DUINO
 | 
			
		||||
    MCU_LDSCRIPT = STM32F103x8_stm32duino_bootloader
 | 
			
		||||
    BOARD = STM32_F103_STM32DUINO
 | 
			
		||||
    # STM32F103 does NOT have an USB bootloader in ROM (only serial), so setting anything here does not make much sense
 | 
			
		||||
    STM32_BOOTLOADER_ADDRESS = 0x80000000
 | 
			
		||||
    BOOTLOADER_TYPE = stm32duino
 | 
			
		||||
 | 
			
		||||
    # Options to pass to dfu-util when flashing
 | 
			
		||||
    DFU_ARGS = -d 1EAF:0003 -a 2 -R
 | 
			
		||||
| 
						 | 
				
			
			@ -160,4 +183,17 @@ ifeq ($(strip $(BOOTLOADER)), stm32duino)
 | 
			
		|||
endif
 | 
			
		||||
ifeq ($(strip $(BOOTLOADER)), tinyuf2)
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_TINYUF2
 | 
			
		||||
    BOOTLOADER_TYPE = tinyuf2
 | 
			
		||||
endif
 | 
			
		||||
ifeq ($(strip $(BOOTLOADER)), halfkay)
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_HALFKAY
 | 
			
		||||
    BOOTLOADER_TYPE = halfkay
 | 
			
		||||
endif
 | 
			
		||||
ifeq ($(strip $(BOOTLOADER)), md-boot)
 | 
			
		||||
    OPT_DEFS += -DBOOTLOADER_MD_BOOT
 | 
			
		||||
    BOOTLOADER_TYPE = md_boot
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(strip $(BOOTLOADER_TYPE)),)
 | 
			
		||||
    BOOTLOADER_TYPE = none
 | 
			
		||||
endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,7 +57,7 @@
 | 
			
		|||
        },
 | 
			
		||||
        "bootloader": {
 | 
			
		||||
            "type": "string",
 | 
			
		||||
            "enum": ["atmel-dfu", "bootloadhid", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "micronucleus", "qmk-dfu", "qmk-hid", "stm32-dfu", "stm32duino", "gd32v-dfu", "wb32-dfu", "unknown", "usbasploader", "USBasp", "tinyuf2"],
 | 
			
		||||
            "enum": ["atmel-dfu", "bootloadhid", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "md-boot", "micronucleus", "qmk-dfu", "qmk-hid", "stm32-dfu", "stm32duino", "gd32v-dfu", "wb32-dfu", "unknown", "usbasploader", "USBasp", "tinyuf2"],
 | 
			
		||||
        },
 | 
			
		||||
        "bootloader_instructions": {
 | 
			
		||||
            "type": "string",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,8 @@
 | 
			
		|||
# MCU name
 | 
			
		||||
MCU = MK20DX256
 | 
			
		||||
 | 
			
		||||
# Bootloader selection
 | 
			
		||||
BOOTLOADER = halfkay
 | 
			
		||||
 | 
			
		||||
# Enter lower-power sleep mode when on the ChibiOS idle thread
 | 
			
		||||
OPT_DEFS += -DCORTEX_ENABLE_WFI_IDLE=TRUE
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,5 +2,8 @@
 | 
			
		|||
MCU = MKL26Z64
 | 
			
		||||
USE_CHIBIOS_CONTRIB = yes
 | 
			
		||||
 | 
			
		||||
# Bootloader selection
 | 
			
		||||
BOOTLOADER = halfkay
 | 
			
		||||
 | 
			
		||||
# Enter lower-power sleep mode when on the ChibiOS idle thread
 | 
			
		||||
OPT_DEFS += -DCORTEX_ENABLE_WFI_IDLE=TRUE
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,9 @@ SRC += config_led.c
 | 
			
		|||
ARM_ATSAM = SAMD51J18A
 | 
			
		||||
MCU = cortex-m4
 | 
			
		||||
 | 
			
		||||
# Bootloader selection
 | 
			
		||||
BOOTLOADER = md-boot
 | 
			
		||||
 | 
			
		||||
# Build Options
 | 
			
		||||
#   change yes to no to disable
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,9 @@ SRC += config_led.c
 | 
			
		|||
ARM_ATSAM = SAMD51J18A
 | 
			
		||||
MCU = cortex-m4
 | 
			
		||||
 | 
			
		||||
# Bootloader selection
 | 
			
		||||
BOOTLOADER = md-boot
 | 
			
		||||
 | 
			
		||||
# Build Options
 | 
			
		||||
#   change yes to no to disable
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ MCU = atmega32a
 | 
			
		|||
F_CPU = 16000000
 | 
			
		||||
 | 
			
		||||
# Bootloader selection
 | 
			
		||||
BOOTLOADER = USBasp
 | 
			
		||||
BOOTLOADER = usbasploader
 | 
			
		||||
 | 
			
		||||
# Build Options
 | 
			
		||||
#   change yes to no to disable
 | 
			
		||||
| 
						 | 
				
			
			@ -21,4 +21,4 @@ RGBLIGHT_ENABLE = yes       # Enable keyboard RGB underglow
 | 
			
		|||
AUDIO_ENABLE = no           # Audio output
 | 
			
		||||
CUSTOM_MATRIX = lite
 | 
			
		||||
 | 
			
		||||
SRC += matrix.c
 | 
			
		||||
SRC += matrix.c
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ MCU = STM32F103
 | 
			
		|||
MCU_LDSCRIPT = STM32F103xB_stm32duino_bootloader
 | 
			
		||||
OPT_DEFS += -DBOOTLOADER_STM32DUINO
 | 
			
		||||
BOARD = STM32_F103_STM32DUINO
 | 
			
		||||
STM32_BOOTLOADER_ADDRESS = 0x80000000
 | 
			
		||||
BOOTLOADER_TYPE = stm32duino
 | 
			
		||||
DFU_ARGS = -d 1EAF:0003 -a 2 -R
 | 
			
		||||
DFU_SUFFIX_ARGS = -v 1EAF -p 0003
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
MCU = atmega32a
 | 
			
		||||
 | 
			
		||||
# Bootloader selection
 | 
			
		||||
BOOTLOADER = bootloadHID
 | 
			
		||||
BOOTLOADER = bootloadhid
 | 
			
		||||
 | 
			
		||||
# Build Options
 | 
			
		||||
#   change yes to no to disable
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,13 +15,18 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
#include "samd51j18a.h"
 | 
			
		||||
#include "md_bootloader.h"
 | 
			
		||||
 | 
			
		||||
// Set watchdog timer to reset. Directs the bootloader to stay in programming mode.
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
#include "samd51j18a.h"
 | 
			
		||||
 | 
			
		||||
#ifdef KEYBOARD_massdrop_ctrl
 | 
			
		||||
    // CTRL keyboards released with bootloader version below must use RAM method. Otherwise use WDT method.
 | 
			
		||||
// WARNING: These are only for CTRL bootloader release "v2.18Jun 22 2018 17:28:08" for bootloader_jump support
 | 
			
		||||
extern uint32_t _eram;
 | 
			
		||||
 | 
			
		||||
#define BOOTLOADER_MAGIC 0x3B9ACA00
 | 
			
		||||
#define MAGIC_ADDR (uint32_t *)((intptr_t)(&_eram) - 4)
 | 
			
		||||
 | 
			
		||||
// CTRL keyboards released with bootloader version below must use RAM method. Otherwise use WDT method.
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    uint8_t  ver_ram_method[] = "v2.18Jun 22 2018 17:28:08";  // The version to match (NULL terminated by compiler)
 | 
			
		||||
    uint8_t *ver_check        = ver_ram_method;               // Pointer to version match string for traversal
 | 
			
		||||
    uint8_t *ver_rom          = (uint8_t *)0x21A0;            // Pointer to address in ROM where this specific bootloader version would exist
 | 
			
		||||
| 
						 | 
				
			
			@ -34,24 +39,28 @@ void bootloader_jump(void) {
 | 
			
		|||
    if (!*ver_check) {                   // If check version pointer is NULL, all characters have matched
 | 
			
		||||
        *MAGIC_ADDR = BOOTLOADER_MAGIC;  // Set magic number into RAM
 | 
			
		||||
        NVIC_SystemReset();              // Perform system reset
 | 
			
		||||
        while (1) {
 | 
			
		||||
        }  // Won't get here
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        while (1);  // Won't get here
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
// Set watchdog timer to reset. Directs the bootloader to stay in programming mode.
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    WDT->CTRLA.bit.ENABLE = 0;
 | 
			
		||||
    while (WDT->SYNCBUSY.bit.ENABLE) {
 | 
			
		||||
    }
 | 
			
		||||
    while (WDT->CTRLA.bit.ENABLE) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while (WDT->SYNCBUSY.bit.ENABLE);
 | 
			
		||||
    while (WDT->CTRLA.bit.ENABLE);
 | 
			
		||||
 | 
			
		||||
    WDT->CONFIG.bit.WINDOW   = 0;
 | 
			
		||||
    WDT->CONFIG.bit.PER      = 0;
 | 
			
		||||
    WDT->EWCTRL.bit.EWOFFSET = 0;
 | 
			
		||||
    WDT->CTRLA.bit.ENABLE    = 1;
 | 
			
		||||
    while (WDT->SYNCBUSY.bit.ENABLE) {
 | 
			
		||||
    }
 | 
			
		||||
    while (!WDT->CTRLA.bit.ENABLE) {
 | 
			
		||||
    }
 | 
			
		||||
    while (1) {
 | 
			
		||||
    }  // Wait on timeout
 | 
			
		||||
 | 
			
		||||
    while (WDT->SYNCBUSY.bit.ENABLE);
 | 
			
		||||
    while (!WDT->CTRLA.bit.ENABLE);
 | 
			
		||||
 | 
			
		||||
    while (1);  // Wait on timeout
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,293 +0,0 @@
 | 
			
		|||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <avr/io.h>
 | 
			
		||||
#include <avr/eeprom.h>
 | 
			
		||||
#include <avr/interrupt.h>
 | 
			
		||||
#include <avr/wdt.h>
 | 
			
		||||
#include <util/delay.h>
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
#include <avr/boot.h>
 | 
			
		||||
 | 
			
		||||
#ifdef PROTOCOL_LUFA
 | 
			
		||||
#    include <LUFA/Drivers/USB/USB.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** \brief Bootloader Size in *bytes*
 | 
			
		||||
 *
 | 
			
		||||
 * AVR Boot section size are defined by setting BOOTSZ fuse in fact. Consult with your MCU datasheet.
 | 
			
		||||
 * Note that 'Word'(2 bytes) size and address are used in datasheet while TMK uses 'Byte'.
 | 
			
		||||
 *
 | 
			
		||||
 * Size of Bootloaders in bytes:
 | 
			
		||||
 *   Atmel DFU loader(ATmega32U4)   4096
 | 
			
		||||
 *   Atmel DFU loader(AT90USB128)   8192
 | 
			
		||||
 *   LUFA bootloader(ATmega32U4)    4096
 | 
			
		||||
 *   Arduino Caterina(ATmega32U4)   4096
 | 
			
		||||
 *   USBaspLoader(ATmega***)        2048
 | 
			
		||||
 *   Teensy   halfKay(ATmega32U4)   512
 | 
			
		||||
 *   Teensy++ halfKay(AT90USB128)   1024
 | 
			
		||||
 *
 | 
			
		||||
 * AVR Boot section is located at the end of Flash memory like the followings.
 | 
			
		||||
 *
 | 
			
		||||
 * byte     Atmel/LUFA(ATMega32u4)          byte     Atmel(AT90SUB128)
 | 
			
		||||
 * 0x0000   +---------------+               0x00000  +---------------+
 | 
			
		||||
 *          |               |                        |               |
 | 
			
		||||
 *          |               |                        |               |
 | 
			
		||||
 *          |  Application  |                        |  Application  |
 | 
			
		||||
 *          |               |                        |               |
 | 
			
		||||
 *          =               =                        =               =
 | 
			
		||||
 *          |               | 32KB-4KB               |               | 128KB-8KB
 | 
			
		||||
 * 0x7000   +---------------+               0x1E000  +---------------+
 | 
			
		||||
 *          |  Bootloader   | 4KB                    |  Bootloader   | 8KB
 | 
			
		||||
 * 0x7FFF   +---------------+               0x1FFFF  +---------------+
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * byte     Teensy(ATMega32u4)              byte     Teensy++(AT90SUB128)
 | 
			
		||||
 * 0x0000   +---------------+               0x00000  +---------------+
 | 
			
		||||
 *          |               |                        |               |
 | 
			
		||||
 *          |               |                        |               |
 | 
			
		||||
 *          |  Application  |                        |  Application  |
 | 
			
		||||
 *          |               |                        |               |
 | 
			
		||||
 *          =               =                        =               =
 | 
			
		||||
 *          |               | 32KB-512B              |               | 128KB-1KB
 | 
			
		||||
 * 0x7E00   +---------------+               0x1FC00  +---------------+
 | 
			
		||||
 *          |  Bootloader   | 512B                   |  Bootloader   | 1KB
 | 
			
		||||
 * 0x7FFF   +---------------+               0x1FFFF  +---------------+
 | 
			
		||||
 */
 | 
			
		||||
#define FLASH_SIZE (FLASHEND + 1L)
 | 
			
		||||
 | 
			
		||||
#if !defined(BOOTLOADER_SIZE)
 | 
			
		||||
uint16_t bootloader_start;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// compatibility between ATMega8 and ATMega88
 | 
			
		||||
#if !defined(MCUCSR)
 | 
			
		||||
#    if defined(MCUSR)
 | 
			
		||||
#        define MCUCSR MCUSR
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** \brief Entering the Bootloader via Software
 | 
			
		||||
 *
 | 
			
		||||
 * http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
 | 
			
		||||
 */
 | 
			
		||||
#define BOOTLOADER_RESET_KEY 0xB007B007
 | 
			
		||||
uint32_t reset_key __attribute__((section(".noinit,\"aw\",@nobits;")));
 | 
			
		||||
 | 
			
		||||
/** \brief initialize MCU status by watchdog reset
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void bootloader_jump(void) {
 | 
			
		||||
#if !defined(BOOTLOADER_SIZE)
 | 
			
		||||
    uint8_t high_fuse = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
 | 
			
		||||
 | 
			
		||||
    if (high_fuse & ~(FUSE_BOOTSZ0 & FUSE_BOOTSZ1)) {
 | 
			
		||||
        bootloader_start = (FLASH_SIZE - 512) >> 1;
 | 
			
		||||
    } else if (high_fuse & ~(FUSE_BOOTSZ1)) {
 | 
			
		||||
        bootloader_start = (FLASH_SIZE - 1024) >> 1;
 | 
			
		||||
    } else if (high_fuse & ~(FUSE_BOOTSZ0)) {
 | 
			
		||||
        bootloader_start = (FLASH_SIZE - 2048) >> 1;
 | 
			
		||||
    } else {
 | 
			
		||||
        bootloader_start = (FLASH_SIZE - 4096) >> 1;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // Something like this might work, but it compiled larger than the block above
 | 
			
		||||
    // bootloader_start = FLASH_SIZE - (256 << (~high_fuse & 0b110 >> 1));
 | 
			
		||||
 | 
			
		||||
#if defined(BOOTLOADER_HALFKAY)
 | 
			
		||||
    //  http://www.pjrc.com/teensy/jump_to_bootloader.html
 | 
			
		||||
    cli();
 | 
			
		||||
    // disable watchdog, if enabled (it's not)
 | 
			
		||||
    // disable all peripherals
 | 
			
		||||
    // a shutdown call might make sense here
 | 
			
		||||
    UDCON  = 1;
 | 
			
		||||
    USBCON = (1 << FRZCLK);  // disable USB
 | 
			
		||||
    UCSR1B = 0;
 | 
			
		||||
    _delay_ms(5);
 | 
			
		||||
#    if defined(__AVR_AT90USB162__)  // Teensy 1.0
 | 
			
		||||
    EIMSK  = 0;
 | 
			
		||||
    PCICR  = 0;
 | 
			
		||||
    SPCR   = 0;
 | 
			
		||||
    ACSR   = 0;
 | 
			
		||||
    EECR   = 0;
 | 
			
		||||
    TIMSK0 = 0;
 | 
			
		||||
    TIMSK1 = 0;
 | 
			
		||||
    UCSR1B = 0;
 | 
			
		||||
    DDRB   = 0;
 | 
			
		||||
    DDRC   = 0;
 | 
			
		||||
    DDRD   = 0;
 | 
			
		||||
    PORTB  = 0;
 | 
			
		||||
    PORTC  = 0;
 | 
			
		||||
    PORTD  = 0;
 | 
			
		||||
    asm volatile("jmp 0x3E00");
 | 
			
		||||
#    elif defined(__AVR_ATmega32U4__)   // Teensy 2.0
 | 
			
		||||
    EIMSK  = 0;
 | 
			
		||||
    PCICR  = 0;
 | 
			
		||||
    SPCR   = 0;
 | 
			
		||||
    ACSR   = 0;
 | 
			
		||||
    EECR   = 0;
 | 
			
		||||
    ADCSRA = 0;
 | 
			
		||||
    TIMSK0 = 0;
 | 
			
		||||
    TIMSK1 = 0;
 | 
			
		||||
    TIMSK3 = 0;
 | 
			
		||||
    TIMSK4 = 0;
 | 
			
		||||
    UCSR1B = 0;
 | 
			
		||||
    TWCR   = 0;
 | 
			
		||||
    DDRB   = 0;
 | 
			
		||||
    DDRC   = 0;
 | 
			
		||||
    DDRD   = 0;
 | 
			
		||||
    DDRE   = 0;
 | 
			
		||||
    DDRF   = 0;
 | 
			
		||||
    TWCR   = 0;
 | 
			
		||||
    PORTB  = 0;
 | 
			
		||||
    PORTC  = 0;
 | 
			
		||||
    PORTD  = 0;
 | 
			
		||||
    PORTE  = 0;
 | 
			
		||||
    PORTF  = 0;
 | 
			
		||||
    asm volatile("jmp 0x7E00");
 | 
			
		||||
#    elif defined(__AVR_AT90USB646__)   // Teensy++ 1.0
 | 
			
		||||
    EIMSK  = 0;
 | 
			
		||||
    PCICR  = 0;
 | 
			
		||||
    SPCR   = 0;
 | 
			
		||||
    ACSR   = 0;
 | 
			
		||||
    EECR   = 0;
 | 
			
		||||
    ADCSRA = 0;
 | 
			
		||||
    TIMSK0 = 0;
 | 
			
		||||
    TIMSK1 = 0;
 | 
			
		||||
    TIMSK2 = 0;
 | 
			
		||||
    TIMSK3 = 0;
 | 
			
		||||
    UCSR1B = 0;
 | 
			
		||||
    TWCR   = 0;
 | 
			
		||||
    DDRA   = 0;
 | 
			
		||||
    DDRB   = 0;
 | 
			
		||||
    DDRC   = 0;
 | 
			
		||||
    DDRD   = 0;
 | 
			
		||||
    DDRE   = 0;
 | 
			
		||||
    DDRF   = 0;
 | 
			
		||||
    PORTA  = 0;
 | 
			
		||||
    PORTB  = 0;
 | 
			
		||||
    PORTC  = 0;
 | 
			
		||||
    PORTD  = 0;
 | 
			
		||||
    PORTE  = 0;
 | 
			
		||||
    PORTF  = 0;
 | 
			
		||||
    asm volatile("jmp 0xFC00");
 | 
			
		||||
#    elif defined(__AVR_AT90USB1286__)  // Teensy++ 2.0
 | 
			
		||||
    EIMSK  = 0;
 | 
			
		||||
    PCICR  = 0;
 | 
			
		||||
    SPCR   = 0;
 | 
			
		||||
    ACSR   = 0;
 | 
			
		||||
    EECR   = 0;
 | 
			
		||||
    ADCSRA = 0;
 | 
			
		||||
    TIMSK0 = 0;
 | 
			
		||||
    TIMSK1 = 0;
 | 
			
		||||
    TIMSK2 = 0;
 | 
			
		||||
    TIMSK3 = 0;
 | 
			
		||||
    UCSR1B = 0;
 | 
			
		||||
    TWCR   = 0;
 | 
			
		||||
    DDRA   = 0;
 | 
			
		||||
    DDRB   = 0;
 | 
			
		||||
    DDRC   = 0;
 | 
			
		||||
    DDRD   = 0;
 | 
			
		||||
    DDRE   = 0;
 | 
			
		||||
    DDRF   = 0;
 | 
			
		||||
    PORTA  = 0;
 | 
			
		||||
    PORTB  = 0;
 | 
			
		||||
    PORTC  = 0;
 | 
			
		||||
    PORTD  = 0;
 | 
			
		||||
    PORTE  = 0;
 | 
			
		||||
    PORTF  = 0;
 | 
			
		||||
    asm volatile("jmp 0x1FC00");
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#elif defined(BOOTLOADER_CATERINA)
 | 
			
		||||
    // this block may be optional
 | 
			
		||||
    // TODO: figure it out
 | 
			
		||||
 | 
			
		||||
    uint16_t *const bootKeyPtr = (uint16_t *)0x0800;
 | 
			
		||||
 | 
			
		||||
    // Value used by Caterina bootloader use to determine whether to run the
 | 
			
		||||
    // sketch or the bootloader programmer.
 | 
			
		||||
    uint16_t bootKey = 0x7777;
 | 
			
		||||
 | 
			
		||||
    *bootKeyPtr = bootKey;
 | 
			
		||||
 | 
			
		||||
    // setup watchdog timeout
 | 
			
		||||
    wdt_enable(WDTO_60MS);
 | 
			
		||||
 | 
			
		||||
    while (1) {
 | 
			
		||||
    }  // wait for watchdog timer to trigger
 | 
			
		||||
 | 
			
		||||
#elif defined(BOOTLOADER_USBASP)
 | 
			
		||||
    // Taken with permission of Stephan Baerwolf from https://github.com/tinyusbboard/API/blob/master/apipage.c
 | 
			
		||||
    wdt_enable(WDTO_15MS);
 | 
			
		||||
    wdt_reset();
 | 
			
		||||
    asm volatile("cli                    \n\t"
 | 
			
		||||
                 "ldi    r29 ,       %[ramendhi] \n\t"
 | 
			
		||||
                 "ldi    r28 ,       %[ramendlo] \n\t"
 | 
			
		||||
#    if (FLASHEND > 131071)
 | 
			
		||||
                 "ldi    r18 ,       %[bootaddrhi]   \n\t"
 | 
			
		||||
                 "st     Y+,         r18     \n\t"
 | 
			
		||||
#    endif
 | 
			
		||||
                 "ldi    r18 ,       %[bootaddrme]   \n\t"
 | 
			
		||||
                 "st     Y+,     r18     \n\t"
 | 
			
		||||
                 "ldi    r18 ,       %[bootaddrlo]   \n\t"
 | 
			
		||||
                 "st     Y+,     r18     \n\t"
 | 
			
		||||
                 "out    %[mcucsrio],    __zero_reg__    \n\t"
 | 
			
		||||
                 "bootloader_startup_loop%=:         \n\t"
 | 
			
		||||
                 "rjmp bootloader_startup_loop%=     \n\t"
 | 
			
		||||
                 :
 | 
			
		||||
                 : [mcucsrio] "I"(_SFR_IO_ADDR(MCUCSR)),
 | 
			
		||||
#    if (FLASHEND > 131071)
 | 
			
		||||
                   [ramendhi] "M"(((RAMEND - 2) >> 8) & 0xff), [ramendlo] "M"(((RAMEND - 2) >> 0) & 0xff), [bootaddrhi] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 16) & 0xff),
 | 
			
		||||
#    else
 | 
			
		||||
                   [ramendhi] "M"(((RAMEND - 1) >> 8) & 0xff), [ramendlo] "M"(((RAMEND - 1) >> 0) & 0xff),
 | 
			
		||||
#    endif
 | 
			
		||||
                   [bootaddrme] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 8) & 0xff), [bootaddrlo] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 0) & 0xff));
 | 
			
		||||
 | 
			
		||||
#else  // Assume remaining boards are DFU, even if the flag isn't set
 | 
			
		||||
 | 
			
		||||
#    if !(defined(__AVR_ATmega32A__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATtiny85__))  // no USB - maybe BOOTLOADER_BOOTLOADHID instead though?
 | 
			
		||||
    UDCON  = 1;
 | 
			
		||||
    USBCON = (1 << FRZCLK);  // disable USB
 | 
			
		||||
    UCSR1B = 0;
 | 
			
		||||
    _delay_ms(5);  // 5 seems to work fine
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#    ifdef BOOTLOADER_BOOTLOADHID
 | 
			
		||||
    // force bootloadHID to stay in bootloader mode, so that it waits
 | 
			
		||||
    // for a new firmware to be flashed
 | 
			
		||||
    eeprom_write_byte((uint8_t *)1, 0x00);
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
    // watchdog reset
 | 
			
		||||
    reset_key = BOOTLOADER_RESET_KEY;
 | 
			
		||||
    wdt_enable(WDTO_250MS);
 | 
			
		||||
    for (;;)
 | 
			
		||||
        ;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* this runs before main() */
 | 
			
		||||
void bootloader_jump_after_watchdog_reset(void) __attribute__((used, naked, section(".init3")));
 | 
			
		||||
void bootloader_jump_after_watchdog_reset(void) {
 | 
			
		||||
#ifndef BOOTLOADER_HALFKAY
 | 
			
		||||
    if ((MCUCSR & (1 << WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
 | 
			
		||||
        reset_key = 0;
 | 
			
		||||
 | 
			
		||||
        // My custom USBasploader requires this to come up.
 | 
			
		||||
        MCUCSR = 0;
 | 
			
		||||
 | 
			
		||||
        // Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
 | 
			
		||||
        MCUCSR &= ~(1 << WDRF);
 | 
			
		||||
        wdt_disable();
 | 
			
		||||
 | 
			
		||||
// This is compled into 'icall', address should be in word unit, not byte.
 | 
			
		||||
#    ifdef BOOTLOADER_SIZE
 | 
			
		||||
        ((void (*)(void))((FLASH_SIZE - BOOTLOADER_SIZE) >> 1))();
 | 
			
		||||
#    else
 | 
			
		||||
        asm("ijmp" ::"z"(bootloader_start));
 | 
			
		||||
#    endif
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								platforms/avr/bootloaders/bootloadhid.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								platforms/avr/bootloaders/bootloadhid.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
/* Copyright 2021 QMK
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
#include <avr/eeprom.h>
 | 
			
		||||
#include <avr/wdt.h>
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    // force bootloadHID to stay in bootloader mode, so that it waits
 | 
			
		||||
    // for a new firmware to be flashed
 | 
			
		||||
    // NOTE: this byte is part of QMK's "magic number" - changing it causes the EEPROM to be re-initialized
 | 
			
		||||
    // thus every time the device is flashed the EEPROM will be wiped
 | 
			
		||||
    eeprom_write_byte((uint8_t *)1, 0x00);
 | 
			
		||||
 | 
			
		||||
    // watchdog reset
 | 
			
		||||
    wdt_enable(WDTO_250MS);
 | 
			
		||||
    for (;;)
 | 
			
		||||
        ;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								platforms/avr/bootloaders/caterina.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								platforms/avr/bootloaders/caterina.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
/* Copyright 2021 QMK
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
#include <avr/wdt.h>
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    // this block may be optional
 | 
			
		||||
    // TODO: figure it out
 | 
			
		||||
 | 
			
		||||
    uint16_t *const bootKeyPtr = (uint16_t *)0x0800;
 | 
			
		||||
 | 
			
		||||
    // Value used by Caterina bootloader use to determine whether to run the
 | 
			
		||||
    // sketch or the bootloader programmer.
 | 
			
		||||
    uint16_t bootKey = 0x7777;
 | 
			
		||||
 | 
			
		||||
    *bootKeyPtr = bootKey;
 | 
			
		||||
 | 
			
		||||
    // setup watchdog timeout
 | 
			
		||||
    wdt_enable(WDTO_60MS);
 | 
			
		||||
 | 
			
		||||
    // wait for watchdog timer to trigger
 | 
			
		||||
    while (1) { }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								platforms/avr/bootloaders/dfu.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								platforms/avr/bootloaders/dfu.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
/* Copyright 2021 QMK
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
#include <avr/wdt.h>
 | 
			
		||||
#include <util/delay.h>
 | 
			
		||||
 | 
			
		||||
#define FLASH_SIZE (FLASHEND + 1L)
 | 
			
		||||
 | 
			
		||||
/** \brief Entering the Bootloader via Software
 | 
			
		||||
 *
 | 
			
		||||
 * http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
 | 
			
		||||
 */
 | 
			
		||||
#define BOOTLOADER_RESET_KEY 0xB007B007
 | 
			
		||||
uint32_t reset_key __attribute__((section(".noinit,\"aw\",@nobits;")));
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    UDCON  = 1;
 | 
			
		||||
    USBCON = (1 << FRZCLK);  // disable USB
 | 
			
		||||
    UCSR1B = 0;
 | 
			
		||||
    _delay_ms(5);  // 5 seems to work fine
 | 
			
		||||
 | 
			
		||||
    // watchdog reset
 | 
			
		||||
    reset_key = BOOTLOADER_RESET_KEY;
 | 
			
		||||
    wdt_enable(WDTO_250MS);
 | 
			
		||||
    for (;;)
 | 
			
		||||
        ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* this runs before main() */
 | 
			
		||||
void bootloader_jump_after_watchdog_reset(void) __attribute__((used, naked, section(".init3")));
 | 
			
		||||
void bootloader_jump_after_watchdog_reset(void) {
 | 
			
		||||
    if ((MCUSR & (1 << WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
 | 
			
		||||
        reset_key = 0;
 | 
			
		||||
 | 
			
		||||
        ((void (*)(void))((FLASH_SIZE - BOOTLOADER_SIZE) >> 1))();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										129
									
								
								platforms/avr/bootloaders/halfkay.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								platforms/avr/bootloaders/halfkay.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,129 @@
 | 
			
		|||
/* Copyright 2021 QMK
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
#include <avr/interrupt.h>
 | 
			
		||||
#include <util/delay.h>
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    // http://www.pjrc.com/teensy/jump_to_bootloader.html
 | 
			
		||||
 | 
			
		||||
    cli();
 | 
			
		||||
    // disable watchdog, if enabled (it's not)
 | 
			
		||||
    // disable all peripherals
 | 
			
		||||
    // a shutdown call might make sense here
 | 
			
		||||
    UDCON  = 1;
 | 
			
		||||
    USBCON = (1 << FRZCLK);  // disable USB
 | 
			
		||||
    UCSR1B = 0;
 | 
			
		||||
    _delay_ms(5);
 | 
			
		||||
 | 
			
		||||
#if defined(__AVR_AT90USB162__)  // Teensy 1.0
 | 
			
		||||
    EIMSK  = 0;
 | 
			
		||||
    PCICR  = 0;
 | 
			
		||||
    SPCR   = 0;
 | 
			
		||||
    ACSR   = 0;
 | 
			
		||||
    EECR   = 0;
 | 
			
		||||
    TIMSK0 = 0;
 | 
			
		||||
    TIMSK1 = 0;
 | 
			
		||||
    UCSR1B = 0;
 | 
			
		||||
    DDRB   = 0;
 | 
			
		||||
    DDRC   = 0;
 | 
			
		||||
    DDRD   = 0;
 | 
			
		||||
    PORTB  = 0;
 | 
			
		||||
    PORTC  = 0;
 | 
			
		||||
    PORTD  = 0;
 | 
			
		||||
    asm volatile("jmp 0x3E00");
 | 
			
		||||
#elif defined(__AVR_ATmega32U4__)   // Teensy 2.0
 | 
			
		||||
    EIMSK  = 0;
 | 
			
		||||
    PCICR  = 0;
 | 
			
		||||
    SPCR   = 0;
 | 
			
		||||
    ACSR   = 0;
 | 
			
		||||
    EECR   = 0;
 | 
			
		||||
    ADCSRA = 0;
 | 
			
		||||
    TIMSK0 = 0;
 | 
			
		||||
    TIMSK1 = 0;
 | 
			
		||||
    TIMSK3 = 0;
 | 
			
		||||
    TIMSK4 = 0;
 | 
			
		||||
    UCSR1B = 0;
 | 
			
		||||
    TWCR   = 0;
 | 
			
		||||
    DDRB   = 0;
 | 
			
		||||
    DDRC   = 0;
 | 
			
		||||
    DDRD   = 0;
 | 
			
		||||
    DDRE   = 0;
 | 
			
		||||
    DDRF   = 0;
 | 
			
		||||
    TWCR   = 0;
 | 
			
		||||
    PORTB  = 0;
 | 
			
		||||
    PORTC  = 0;
 | 
			
		||||
    PORTD  = 0;
 | 
			
		||||
    PORTE  = 0;
 | 
			
		||||
    PORTF  = 0;
 | 
			
		||||
    asm volatile("jmp 0x7E00");
 | 
			
		||||
#elif defined(__AVR_AT90USB646__)   // Teensy++ 1.0
 | 
			
		||||
    EIMSK  = 0;
 | 
			
		||||
    PCICR  = 0;
 | 
			
		||||
    SPCR   = 0;
 | 
			
		||||
    ACSR   = 0;
 | 
			
		||||
    EECR   = 0;
 | 
			
		||||
    ADCSRA = 0;
 | 
			
		||||
    TIMSK0 = 0;
 | 
			
		||||
    TIMSK1 = 0;
 | 
			
		||||
    TIMSK2 = 0;
 | 
			
		||||
    TIMSK3 = 0;
 | 
			
		||||
    UCSR1B = 0;
 | 
			
		||||
    TWCR   = 0;
 | 
			
		||||
    DDRA   = 0;
 | 
			
		||||
    DDRB   = 0;
 | 
			
		||||
    DDRC   = 0;
 | 
			
		||||
    DDRD   = 0;
 | 
			
		||||
    DDRE   = 0;
 | 
			
		||||
    DDRF   = 0;
 | 
			
		||||
    PORTA  = 0;
 | 
			
		||||
    PORTB  = 0;
 | 
			
		||||
    PORTC  = 0;
 | 
			
		||||
    PORTD  = 0;
 | 
			
		||||
    PORTE  = 0;
 | 
			
		||||
    PORTF  = 0;
 | 
			
		||||
    asm volatile("jmp 0xFC00");
 | 
			
		||||
#elif defined(__AVR_AT90USB1286__)  // Teensy++ 2.0
 | 
			
		||||
    EIMSK  = 0;
 | 
			
		||||
    PCICR  = 0;
 | 
			
		||||
    SPCR   = 0;
 | 
			
		||||
    ACSR   = 0;
 | 
			
		||||
    EECR   = 0;
 | 
			
		||||
    ADCSRA = 0;
 | 
			
		||||
    TIMSK0 = 0;
 | 
			
		||||
    TIMSK1 = 0;
 | 
			
		||||
    TIMSK2 = 0;
 | 
			
		||||
    TIMSK3 = 0;
 | 
			
		||||
    UCSR1B = 0;
 | 
			
		||||
    TWCR   = 0;
 | 
			
		||||
    DDRA   = 0;
 | 
			
		||||
    DDRB   = 0;
 | 
			
		||||
    DDRC   = 0;
 | 
			
		||||
    DDRD   = 0;
 | 
			
		||||
    DDRE   = 0;
 | 
			
		||||
    DDRF   = 0;
 | 
			
		||||
    PORTA  = 0;
 | 
			
		||||
    PORTB  = 0;
 | 
			
		||||
    PORTC  = 0;
 | 
			
		||||
    PORTD  = 0;
 | 
			
		||||
    PORTE  = 0;
 | 
			
		||||
    PORTF  = 0;
 | 
			
		||||
    asm volatile("jmp 0x1FC00");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								platforms/avr/bootloaders/none.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								platforms/avr/bootloaders/none.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
/* Copyright 2021 QMK
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) { }
 | 
			
		||||
							
								
								
									
										57
									
								
								platforms/avr/bootloaders/usbasploader.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								platforms/avr/bootloaders/usbasploader.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
/* Copyright 2021 QMK
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
#include <avr/wdt.h>
 | 
			
		||||
 | 
			
		||||
#define FLASH_SIZE (FLASHEND + 1L)
 | 
			
		||||
 | 
			
		||||
#if !defined(MCUCSR)
 | 
			
		||||
#    if defined(MCUSR)
 | 
			
		||||
#        define MCUCSR MCUSR
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    // Taken with permission of Stephan Baerwolf from https://github.com/tinyusbboard/API/blob/master/apipage.c
 | 
			
		||||
 | 
			
		||||
    wdt_enable(WDTO_15MS);
 | 
			
		||||
    wdt_reset();
 | 
			
		||||
    asm volatile("cli                    \n\t"
 | 
			
		||||
                 "ldi    r29 ,       %[ramendhi] \n\t"
 | 
			
		||||
                 "ldi    r28 ,       %[ramendlo] \n\t"
 | 
			
		||||
#if (FLASHEND > 131071)
 | 
			
		||||
                 "ldi    r18 ,       %[bootaddrhi]   \n\t"
 | 
			
		||||
                 "st     Y+,         r18     \n\t"
 | 
			
		||||
#endif
 | 
			
		||||
                 "ldi    r18 ,       %[bootaddrme]   \n\t"
 | 
			
		||||
                 "st     Y+,     r18     \n\t"
 | 
			
		||||
                 "ldi    r18 ,       %[bootaddrlo]   \n\t"
 | 
			
		||||
                 "st     Y+,     r18     \n\t"
 | 
			
		||||
                 "out    %[mcucsrio],    __zero_reg__    \n\t"
 | 
			
		||||
                 "bootloader_startup_loop%=:         \n\t"
 | 
			
		||||
                 "rjmp bootloader_startup_loop%=     \n\t"
 | 
			
		||||
                 :
 | 
			
		||||
                 : [mcucsrio] "I"(_SFR_IO_ADDR(MCUCSR)),
 | 
			
		||||
#if (FLASHEND > 131071)
 | 
			
		||||
                   [ramendhi] "M"(((RAMEND - 2) >> 8) & 0xff), [ramendlo] "M"(((RAMEND - 2) >> 0) & 0xff), [bootaddrhi] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 16) & 0xff),
 | 
			
		||||
#else
 | 
			
		||||
                   [ramendhi] "M"(((RAMEND - 1) >> 8) & 0xff), [ramendlo] "M"(((RAMEND - 1) >> 0) & 0xff),
 | 
			
		||||
#endif
 | 
			
		||||
                   [bootaddrme] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 8) & 0xff), [bootaddrlo] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 0) & 0xff));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,145 +0,0 @@
 | 
			
		|||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
#include <ch.h>
 | 
			
		||||
#include <hal.h>
 | 
			
		||||
#include "wait.h"
 | 
			
		||||
 | 
			
		||||
/* This code should be checked whether it runs correctly on platforms */
 | 
			
		||||
#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
 | 
			
		||||
#define BOOTLOADER_MAGIC 0xDEADBEEF
 | 
			
		||||
#define MAGIC_ADDR (unsigned long *)(SYMVAL(__ram0_end__) - 4)
 | 
			
		||||
 | 
			
		||||
#ifndef STM32_BOOTLOADER_DUAL_BANK
 | 
			
		||||
#    define STM32_BOOTLOADER_DUAL_BANK FALSE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef BOOTLOADER_TINYUF2
 | 
			
		||||
 | 
			
		||||
#    define DBL_TAP_MAGIC 0xf01669ef  // From tinyuf2's board_api.h
 | 
			
		||||
 | 
			
		||||
// defined by linker script
 | 
			
		||||
extern uint32_t _board_dfu_dbl_tap[];
 | 
			
		||||
#    define DBL_TAP_REG _board_dfu_dbl_tap[0]
 | 
			
		||||
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    DBL_TAP_REG = DBL_TAP_MAGIC;
 | 
			
		||||
    NVIC_SystemReset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void enter_bootloader_mode_if_requested(void) { /* not needed, no two-stage reset */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif STM32_BOOTLOADER_DUAL_BANK
 | 
			
		||||
 | 
			
		||||
// Need pin definitions
 | 
			
		||||
#    include "config_common.h"
 | 
			
		||||
 | 
			
		||||
#    ifndef STM32_BOOTLOADER_DUAL_BANK_GPIO
 | 
			
		||||
#        error "No STM32_BOOTLOADER_DUAL_BANK_GPIO defined, don't know which pin to toggle"
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#    ifndef STM32_BOOTLOADER_DUAL_BANK_POLARITY
 | 
			
		||||
#        define STM32_BOOTLOADER_DUAL_BANK_POLARITY 0
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#    ifndef STM32_BOOTLOADER_DUAL_BANK_DELAY
 | 
			
		||||
#        define STM32_BOOTLOADER_DUAL_BANK_DELAY 100000
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
extern uint32_t __ram0_end__;
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) void bootloader_jump(void) {
 | 
			
		||||
    // For STM32 MCUs with dual-bank flash, and we're incapable of jumping to the bootloader. The first valid flash
 | 
			
		||||
    // bank is executed unconditionally after a reset, so it doesn't enter DFU unless BOOT0 is high. Instead, we do
 | 
			
		||||
    // it with hardware...in this case, we pull a GPIO high/low depending on the configuration, connects 3.3V to
 | 
			
		||||
    // BOOT0's RC charging circuit, lets it charge the capacitor, and issue a system reset. See the QMK discord
 | 
			
		||||
    // #hardware channel pins for an example circuit.
 | 
			
		||||
    palSetPadMode(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_MODE_OUTPUT_PUSHPULL);
 | 
			
		||||
#    if STM32_BOOTLOADER_DUAL_BANK_POLARITY
 | 
			
		||||
    palSetPad(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO));
 | 
			
		||||
#    else
 | 
			
		||||
    palClearPad(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO));
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
    // Wait for a while for the capacitor to charge
 | 
			
		||||
    wait_ms(100);
 | 
			
		||||
 | 
			
		||||
    // Issue a system reset to get the ROM bootloader to execute, with BOOT0 high
 | 
			
		||||
    NVIC_SystemReset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void enter_bootloader_mode_if_requested(void) {}  // not needed at all, but if anybody attempts to invoke it....
 | 
			
		||||
 | 
			
		||||
#elif defined(STM32_BOOTLOADER_ADDRESS)  // STM32_BOOTLOADER_DUAL_BANK
 | 
			
		||||
 | 
			
		||||
extern uint32_t __ram0_end__;
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) void bootloader_jump(void) {
 | 
			
		||||
    *MAGIC_ADDR = BOOTLOADER_MAGIC;  // set magic flag => reset handler will jump into boot loader
 | 
			
		||||
    NVIC_SystemReset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void enter_bootloader_mode_if_requested(void) {
 | 
			
		||||
    unsigned long *check = MAGIC_ADDR;
 | 
			
		||||
    if (*check == BOOTLOADER_MAGIC) {
 | 
			
		||||
        *check = 0;
 | 
			
		||||
        __set_CONTROL(0);
 | 
			
		||||
        __set_MSP(*(__IO uint32_t *)STM32_BOOTLOADER_ADDRESS);
 | 
			
		||||
        __enable_irq();
 | 
			
		||||
 | 
			
		||||
        typedef void (*BootJump_t)(void);
 | 
			
		||||
        BootJump_t boot_jump = *(BootJump_t *)(STM32_BOOTLOADER_ADDRESS + 4);
 | 
			
		||||
        boot_jump();
 | 
			
		||||
        while (1)
 | 
			
		||||
            ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(GD32VF103)
 | 
			
		||||
 | 
			
		||||
#    define DBGMCU_KEY_UNLOCK 0x4B5A6978
 | 
			
		||||
#    define DBGMCU_CMD_RESET 0x1
 | 
			
		||||
 | 
			
		||||
__IO uint32_t *DBGMCU_KEY = (uint32_t *)DBGMCU_BASE + 0x0CU;
 | 
			
		||||
__IO uint32_t *DBGMCU_CMD = (uint32_t *)DBGMCU_BASE + 0x08U;
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) void bootloader_jump(void) {
 | 
			
		||||
    /* The MTIMER unit of the GD32VF103 doesn't have the MSFRST
 | 
			
		||||
     * register to generate a software reset request.
 | 
			
		||||
     * BUT instead two undocumented registers in the debug peripheral
 | 
			
		||||
     * that allow issueing a software reset. WHO would need the MSFRST
 | 
			
		||||
     * register anyway? Source:
 | 
			
		||||
     * https://github.com/esmil/gd32vf103inator/blob/master/include/gd32vf103/dbg.h */
 | 
			
		||||
    *DBGMCU_KEY = DBGMCU_KEY_UNLOCK;
 | 
			
		||||
    *DBGMCU_CMD = DBGMCU_CMD_RESET;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void enter_bootloader_mode_if_requested(void) { /* Jumping to bootloader is not possible from user code. */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(KL2x) || defined(K20x) || defined(MK66F18) || defined(MIMXRT1062)  // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS
 | 
			
		||||
/* Kinetis */
 | 
			
		||||
 | 
			
		||||
#    if defined(BOOTLOADER_KIIBOHD)
 | 
			
		||||
/* Kiibohd Bootloader (MCHCK and Infinity KB) */
 | 
			
		||||
#        define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000
 | 
			
		||||
const uint8_t              sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
 | 
			
		||||
__attribute__((weak)) void bootloader_jump(void) {
 | 
			
		||||
    void *volatile vbat = (void *)VBAT;
 | 
			
		||||
    __builtin_memcpy(vbat, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic));
 | 
			
		||||
    // request reset
 | 
			
		||||
    SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    else /* defined(BOOTLOADER_KIIBOHD) */
 | 
			
		||||
/* Default for Kinetis - expecting an ARM Teensy */
 | 
			
		||||
#        include "wait.h"
 | 
			
		||||
__attribute__((weak)) void bootloader_jump(void) {
 | 
			
		||||
    wait_ms(100);
 | 
			
		||||
    __BKPT(0);
 | 
			
		||||
}
 | 
			
		||||
#    endif /* defined(BOOTLOADER_KIIBOHD) */
 | 
			
		||||
 | 
			
		||||
#else /* neither STM32 nor KINETIS */
 | 
			
		||||
__attribute__((weak)) void bootloader_jump(void) {}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										40
									
								
								platforms/chibios/bootloaders/gd32v_dfu.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								platforms/chibios/bootloaders/gd32v_dfu.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
/* Copyright 2021 QMK
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
#include <ch.h>
 | 
			
		||||
 | 
			
		||||
#define DBGMCU_KEY_UNLOCK 0x4B5A6978
 | 
			
		||||
#define DBGMCU_CMD_RESET 0x1
 | 
			
		||||
 | 
			
		||||
__IO uint32_t *DBGMCU_KEY = (uint32_t *)DBGMCU_BASE + 0x0CU;
 | 
			
		||||
__IO uint32_t *DBGMCU_CMD = (uint32_t *)DBGMCU_BASE + 0x08U;
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    /* The MTIMER unit of the GD32VF103 doesn't have the MSFRST
 | 
			
		||||
     * register to generate a software reset request.
 | 
			
		||||
     * BUT instead two undocumented registers in the debug peripheral
 | 
			
		||||
     * that allow issueing a software reset. WHO would need the MSFRST
 | 
			
		||||
     * register anyway? Source:
 | 
			
		||||
     * https://github.com/esmil/gd32vf103inator/blob/master/include/gd32vf103/dbg.h */
 | 
			
		||||
    *DBGMCU_KEY = DBGMCU_KEY_UNLOCK;
 | 
			
		||||
    *DBGMCU_CMD = DBGMCU_CMD_RESET;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Jumping to bootloader is not possible from user code. */
 | 
			
		||||
void enter_bootloader_mode_if_requested(void) { }
 | 
			
		||||
							
								
								
									
										26
									
								
								platforms/chibios/bootloaders/halfkay.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								platforms/chibios/bootloaders/halfkay.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
/* Copyright 2021 QMK
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
#include <ch.h>
 | 
			
		||||
#include "wait.h"
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    wait_ms(100);
 | 
			
		||||
    __BKPT(0);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								platforms/chibios/bootloaders/kiibohd.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								platforms/chibios/bootloaders/kiibohd.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
/* Copyright 2021 QMK
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
#include <ch.h>
 | 
			
		||||
 | 
			
		||||
/* Kiibohd Bootloader (MCHCK and Infinity KB) */
 | 
			
		||||
#define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000
 | 
			
		||||
 | 
			
		||||
const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    void *volatile vbat = (void *)VBAT;
 | 
			
		||||
    __builtin_memcpy(vbat, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic));
 | 
			
		||||
 | 
			
		||||
    // request reset
 | 
			
		||||
    SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								platforms/chibios/bootloaders/none.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								platforms/chibios/bootloaders/none.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
/* Copyright 2021 QMK
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) { }
 | 
			
		||||
							
								
								
									
										96
									
								
								platforms/chibios/bootloaders/stm32_dfu.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								platforms/chibios/bootloaders/stm32_dfu.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,96 @@
 | 
			
		|||
/* Copyright 2021 QMK
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
#include <ch.h>
 | 
			
		||||
#include <hal.h>
 | 
			
		||||
#include "wait.h"
 | 
			
		||||
 | 
			
		||||
extern uint32_t __ram0_end__;
 | 
			
		||||
 | 
			
		||||
#ifndef STM32_BOOTLOADER_DUAL_BANK
 | 
			
		||||
#    define STM32_BOOTLOADER_DUAL_BANK FALSE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if STM32_BOOTLOADER_DUAL_BANK
 | 
			
		||||
#    include "config_common.h"
 | 
			
		||||
 | 
			
		||||
#    ifndef STM32_BOOTLOADER_DUAL_BANK_GPIO
 | 
			
		||||
#        error "No STM32_BOOTLOADER_DUAL_BANK_GPIO defined, don't know which pin to toggle"
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#    ifndef STM32_BOOTLOADER_DUAL_BANK_POLARITY
 | 
			
		||||
#        define STM32_BOOTLOADER_DUAL_BANK_POLARITY 0
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#    ifndef STM32_BOOTLOADER_DUAL_BANK_DELAY
 | 
			
		||||
#        define STM32_BOOTLOADER_DUAL_BANK_DELAY 100000
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    // For STM32 MCUs with dual-bank flash, and we're incapable of jumping to the bootloader. The first valid flash
 | 
			
		||||
    // bank is executed unconditionally after a reset, so it doesn't enter DFU unless BOOT0 is high. Instead, we do
 | 
			
		||||
    // it with hardware...in this case, we pull a GPIO high/low depending on the configuration, connects 3.3V to
 | 
			
		||||
    // BOOT0's RC charging circuit, lets it charge the capacitor, and issue a system reset. See the QMK discord
 | 
			
		||||
    // #hardware channel pins for an example circuit.
 | 
			
		||||
    palSetPadMode(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_MODE_OUTPUT_PUSHPULL);
 | 
			
		||||
#    if STM32_BOOTLOADER_DUAL_BANK_POLARITY
 | 
			
		||||
    palSetPad(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO));
 | 
			
		||||
#    else
 | 
			
		||||
    palClearPad(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO));
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
    // Wait for a while for the capacitor to charge
 | 
			
		||||
    wait_ms(100);
 | 
			
		||||
 | 
			
		||||
    // Issue a system reset to get the ROM bootloader to execute, with BOOT0 high
 | 
			
		||||
    NVIC_SystemReset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// not needed at all, but if anybody attempts to invoke it....
 | 
			
		||||
void enter_bootloader_mode_if_requested(void) { }
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
/* This code should be checked whether it runs correctly on platforms */
 | 
			
		||||
#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
 | 
			
		||||
#define BOOTLOADER_MAGIC 0xDEADBEEF
 | 
			
		||||
#define MAGIC_ADDR (unsigned long *)(SYMVAL(__ram0_end__) - 4)
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    *MAGIC_ADDR = BOOTLOADER_MAGIC;  // set magic flag => reset handler will jump into boot loader
 | 
			
		||||
    NVIC_SystemReset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void enter_bootloader_mode_if_requested(void) {
 | 
			
		||||
    unsigned long *check = MAGIC_ADDR;
 | 
			
		||||
    if (*check == BOOTLOADER_MAGIC) {
 | 
			
		||||
        *check = 0;
 | 
			
		||||
        __set_CONTROL(0);
 | 
			
		||||
        __set_MSP(*(__IO uint32_t *)STM32_BOOTLOADER_ADDRESS);
 | 
			
		||||
        __enable_irq();
 | 
			
		||||
 | 
			
		||||
        typedef void (*BootJump_t)(void);
 | 
			
		||||
        BootJump_t boot_jump = *(BootJump_t *)(STM32_BOOTLOADER_ADDRESS + 4);
 | 
			
		||||
        boot_jump();
 | 
			
		||||
        while (1)
 | 
			
		||||
            ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										24
									
								
								platforms/chibios/bootloaders/stm32duino.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								platforms/chibios/bootloaders/stm32duino.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
/* Copyright 2021 QMK
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
#include <ch.h>
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    NVIC_SystemReset();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								platforms/chibios/bootloaders/tinyuf2.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								platforms/chibios/bootloaders/tinyuf2.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
/* Copyright 2021 QMK
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
#include <ch.h>
 | 
			
		||||
 | 
			
		||||
// From tinyuf2's board_api.h
 | 
			
		||||
#define DBL_TAP_MAGIC 0xF01669EF
 | 
			
		||||
 | 
			
		||||
// defined by linker script
 | 
			
		||||
extern uint32_t _board_dfu_dbl_tap[];
 | 
			
		||||
#define DBL_TAP_REG _board_dfu_dbl_tap[0]
 | 
			
		||||
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
    DBL_TAP_REG = DBL_TAP_MAGIC;
 | 
			
		||||
    NVIC_SystemReset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* not needed, no two-stage reset */
 | 
			
		||||
void enter_bootloader_mode_if_requested(void) { }
 | 
			
		||||
| 
						 | 
				
			
			@ -4,7 +4,7 @@ TMK_COMMON_SRC +=	\
 | 
			
		|||
	$(PLATFORM_COMMON_DIR)/platform.c \
 | 
			
		||||
	$(PLATFORM_COMMON_DIR)/suspend.c \
 | 
			
		||||
	$(PLATFORM_COMMON_DIR)/timer.c \
 | 
			
		||||
	$(PLATFORM_COMMON_DIR)/bootloader.c \
 | 
			
		||||
	$(PLATFORM_COMMON_DIR)/bootloaders/$(BOOTLOADER_TYPE).c
 | 
			
		||||
 | 
			
		||||
# Search Path
 | 
			
		||||
VPATH += $(PLATFORM_PATH)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,4 +16,4 @@
 | 
			
		|||
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
void bootloader_jump(void) {}
 | 
			
		||||
void bootloader_jump(void) { }
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +19,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
#define _ARM_ATSAM_PROTOCOL_H_
 | 
			
		||||
 | 
			
		||||
#include "samd51j18a.h"
 | 
			
		||||
#include "md_bootloader.h"
 | 
			
		||||
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#include "d51_util.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,24 +0,0 @@
 | 
			
		|||
#ifndef _MD_BOOTLOADER_H_
 | 
			
		||||
#define _MD_BOOTLOADER_H_
 | 
			
		||||
 | 
			
		||||
extern uint32_t _srom;
 | 
			
		||||
extern uint32_t _lrom;
 | 
			
		||||
extern uint32_t _erom;
 | 
			
		||||
 | 
			
		||||
#define BOOTLOADER_SERIAL_MAX_SIZE 20  // DO NOT MODIFY!
 | 
			
		||||
 | 
			
		||||
#ifdef KEYBOARD_massdrop_ctrl
 | 
			
		||||
// WARNING: These are only for CTRL bootloader release "v2.18Jun 22 2018 17:28:08" for bootloader_jump support
 | 
			
		||||
extern uint32_t _eram;
 | 
			
		||||
#    define BOOTLOADER_MAGIC 0x3B9ACA00
 | 
			
		||||
#    define MAGIC_ADDR (uint32_t *)((intptr_t)(&_eram) - 4)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef MD_BOOTLOADER
 | 
			
		||||
 | 
			
		||||
#    define MCU_HZ 48000000
 | 
			
		||||
#    define I2C_HZ 0  // Not used
 | 
			
		||||
 | 
			
		||||
#endif  // MD_BOOTLOADER
 | 
			
		||||
 | 
			
		||||
#endif  //_MD_BOOTLOADER_H_
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +28,6 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
#include "samd51.h"
 | 
			
		||||
#include "md_bootloader.h"
 | 
			
		||||
 | 
			
		||||
/* Initialize segments */
 | 
			
		||||
extern uint32_t _sfixed;
 | 
			
		||||
| 
						 | 
				
			
			@ -496,6 +495,11 @@ __attribute__((section(".vectors"))) const DeviceVectors exception_table = {
 | 
			
		|||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// WARNING: These are only for CTRL bootloader release "v2.18Jun 22 2018 17:28:08" for bootloader_jump support
 | 
			
		||||
extern uint32_t _eram;
 | 
			
		||||
#define BOOTLOADER_MAGIC 0x3B9ACA00
 | 
			
		||||
#define MAGIC_ADDR (uint32_t *)((intptr_t)(&_eram) - 4)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief This is the code that gets called on processor reset.
 | 
			
		||||
 * To initialize the device, and call the main() routine.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,7 +51,8 @@
 | 
			
		|||
#include "udi_device_conf.h"
 | 
			
		||||
#include "udi.h"
 | 
			
		||||
#include "udc.h"
 | 
			
		||||
#include "md_bootloader.h"
 | 
			
		||||
 | 
			
		||||
#define BOOTLOADER_SERIAL_MAX_SIZE 20  // DO NOT MODIFY!
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \ingroup udc_group
 | 
			
		||||
| 
						 | 
				
			
			@ -122,6 +123,8 @@ static uint8_t udc_string_product_name[] = USB_DEVICE_PRODUCT_NAME;
 | 
			
		|||
#    define USB_DEVICE_SERIAL_NAME_SIZE 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern uint32_t _srom;
 | 
			
		||||
 | 
			
		||||
uint8_t     usb_device_serial_name_size = 0;
 | 
			
		||||
#if defined USB_DEVICE_SERIAL_USE_BOOTLOADER_SERIAL
 | 
			
		||||
uint8_t     bootloader_serial_number[BOOTLOADER_SERIAL_MAX_SIZE + 1] = "";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue