~ruther/qmk_firmware

3538955778c253e68779605cc67c27e15d195729 — yiancar 6 years ago 7d557a0
Usbasploader bootloader option addition (#6304)

* Added USBasp bootloader option for USBasploader

* author comment

* ifdef fix :)

* Add usbasp target

* Update docs/flashing.md

Co-Authored-By: fauxpark <fauxpark@gmail.com>

* Update docs/flashing.md

Co-Authored-By: fauxpark <fauxpark@gmail.com>

* Update docs/flashing.md

Co-Authored-By: fauxpark <fauxpark@gmail.com>
M bootloader.mk => bootloader.mk +4 -0
@@ 76,6 76,10 @@ ifeq ($(strip $(BOOTLOADER)), bootloadHID)
    OPT_DEFS += -DBOOTLOADER_BOOTLOADHID
    BOOTLOADER_SIZE = 4096
endif
ifeq ($(strip $(BOOTLOADER)), USBasp)
    OPT_DEFS += -DBOOTLOADER_USBASP
    BOOTLOADER_SIZE = 4096
endif

ifdef BOOTLOADER_SIZE
    OPT_DEFS += -DBOOTLOADER_SIZE=$(strip $(BOOTLOADER_SIZE))

M docs/config_options.md => docs/config_options.md +1 -0
@@ 289,6 289,7 @@ This is a [make](https://www.gnu.org/software/make/manual/make.html) file that i
  * `halfkay`
  * `caterina`
  * `bootloadHID`
  * `USBasp`

## Feature Options


M docs/flashing.md => docs/flashing.md +25 -0
@@ 119,6 119,31 @@ Flashing sequence:
3. Flash a .hex file
4. Reset the device into application mode (may be done automatically)

## USBasploader

USBasploader is a bootloader developed by matrixstorm. It is used in some non-USB AVR chips such as the ATmega328P, which run V-USB.

To ensure compatibility with the USBasploader bootloader, make sure this block is present in your `rules.mk`:

    # Bootloader
    #     This definition is optional, and if your keyboard supports multiple bootloaders of
    #     different sizes, comment this out, and the correct address will be loaded
    #     automatically (+60). See bootloader.mk for all options.
    BOOTLOADER = USBasp

Compatible flashers:

* [QMK Toolbox](https://github.com/qmk/qmk_toolbox/releases) (recommended GUI)
* [avrdude](http://www.nongnu.org/avrdude/) with the `usbasp` programmer
* [AVRDUDESS](https://github.com/zkemble/AVRDUDESS)

Flashing sequence:

1. Press the `RESET` keycode, or keep the boot pin shorted to GND while quickly shorting RST to GND
2. Wait for the OS to detect the device
3. Flash a .hex file
4. Reset the device into application mode (may be done automatically)

## STM32

All STM32 chips come preloaded with a factory bootloader that cannot be modified nor deleted. Some STM32 chips have bootloaders that do not come with USB programming (e.g. STM32F103) but the process is still the same.

M keyboards/gingham/rules.mk => keyboards/gingham/rules.mk +1 -3
@@ 49,7 49,7 @@ OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
#   atmega32a    bootloadHID
#
# This uses usbaspbootloader
# BOOTLOADER = atmel-dfu
BOOTLOADER = USBasp

# If you don't know the bootloader type, then you can specify the
# Boot Section Size in *bytes* by uncommenting out the OPT_DEFS line


@@ 58,8 58,6 @@ OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
#   Atmel DFU loader    4096
#   LUFA bootloader     4096
#   USBaspLoader        2048
# OPT_DEFS += -DBOOTLOADER_SIZE=4096
OPT_DEFS += -DBOOTLOADER_SIZE=2048

# Flash program via avrdude, but default command is not suitable.
# You can use plaid:default:program

M tmk_core/avr.mk => tmk_core/avr.mk +4 -0
@@ 245,6 245,10 @@ avrdude-split-left: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware
avrdude-split-right: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware
	$(call EXEC_AVRDUDE,eeprom-righthand.eep)

usbasp: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware
	avrdude -p $(MCU) -c usbasp -U flash:w:$(BUILD_DIR)/$(TARGET).hex


# Convert hex to bin.
bin: $(BUILD_DIR)/$(TARGET).hex
	$(OBJCOPY) -Iihex -Obinary $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin

M tmk_core/common/avr/bootloader.c => tmk_core/common/avr/bootloader.c +43 -34
@@ 65,6 65,13 @@
#define BOOT_SIZE_1024 0b010
#define BOOT_SIZE_2048 0b000

//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


@@ 149,6 156,39 @@ void bootloader_jump(void) {

        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__)) // no USB - maybe BOOTLOADER_BOOTLOADHID instead though?


@@ 172,24 212,19 @@ void bootloader_jump(void) {

}

#ifdef __AVR_ATmega32A__
    // MCUSR is actually called MCUCSR in ATmega32A
    #define MCUSR MCUCSR
#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 ((MCUSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
        if ((MCUCSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
            reset_key = 0;

            // My custom USBasploader requires this to come up.
            MCUSR = 0;
            MCUCSR = 0;

            // Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
            MCUSR &= ~(1<<WDRF);
            MCUCSR &= ~(1<<WDRF);
            wdt_disable();




@@ 202,29 237,3 @@ void bootloader_jump_after_watchdog_reset(void)
        }
    #endif
}


#if 0
    /*
     * USBaspLoader - I'm not sure if this is used at all in any projects
     *                would love to support it if it is -Jack
     */
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
    // This makes custom USBasploader come up.
    MCUSR = 0;

    // initialize ports
    PORTB = 0; PORTC= 0; PORTD = 0;
    DDRB = 0; DDRC= 0; DDRD = 0;

    // disable interrupts
    EIMSK = 0; EECR = 0; SPCR = 0;
    ACSR = 0; SPMCSR = 0; WDTCSR = 0; PCICR = 0;
    TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0;
    ADCSRA = 0; TWCR = 0; UCSR0B = 0;
#endif

    // This is compled into 'icall', address should be in word unit, not byte.
    ((void (*)(void))(BOOTLOADER_START/2))();
}
#endif