forked from mirrors/qmk_userspace
Updates bootloader settings, adds file size check (#2029)
* pull fuse settings for bootloader jump * fix 32a chips * make automatic bootloader selection optional * quantify bootloaders * fixs #164, speeds up dfu reset * fix for chips w/o usb * missing an n * fix bootloader sizes, use words for addresses * fix bmini, pearl, and [[ issue, make things quiet * ignore avr errors on arm for now * update settings for the light * document bootloader stuff * add bootloader title
This commit is contained in:
parent
9113f3387a
commit
9fdc276260
76 changed files with 481 additions and 548 deletions
|
@ -121,22 +121,22 @@ qmk: $(BUILD_DIR)/$(TARGET).hex
|
|||
printf "@ $(TARGET).json\n@=info.json\n" | zipnote -w $(TARGET).qmk
|
||||
|
||||
# Program the device.
|
||||
program: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep
|
||||
program: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep check-size
|
||||
$(PROGRAM_CMD)
|
||||
|
||||
teensy: $(BUILD_DIR)/$(TARGET).hex
|
||||
teensy: $(BUILD_DIR)/$(TARGET).hex check-size
|
||||
$(TEENSY_LOADER_CLI) -mmcu=$(MCU) -w -v $(BUILD_DIR)/$(TARGET).hex
|
||||
|
||||
BATCHISP ?= batchisp
|
||||
|
||||
flip: $(BUILD_DIR)/$(TARGET).hex
|
||||
flip: $(BUILD_DIR)/$(TARGET).hex check-size
|
||||
$(BATCHISP) -hardware usb -device $(MCU) -operation erase f
|
||||
$(BATCHISP) -hardware usb -device $(MCU) -operation loadbuffer $(BUILD_DIR)/$(TARGET).hex program
|
||||
$(BATCHISP) -hardware usb -device $(MCU) -operation start reset 0
|
||||
|
||||
DFU_PROGRAMMER ?= dfu-programmer
|
||||
|
||||
dfu: $(BUILD_DIR)/$(TARGET).hex sizeafter
|
||||
dfu: $(BUILD_DIR)/$(TARGET).hex check-size
|
||||
until $(DFU_PROGRAMMER) $(MCU) get bootloader-version; do\
|
||||
echo "Error: Bootloader not found. Trying again in 5s." ;\
|
||||
sleep 5 ;\
|
||||
|
@ -168,7 +168,7 @@ dfu-ee: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep
|
|||
fi
|
||||
$(DFU_PROGRAMMER) $(MCU) reset
|
||||
|
||||
avrdude: $(BUILD_DIR)/$(TARGET).hex
|
||||
avrdude: $(BUILD_DIR)/$(TARGET).hex check-size
|
||||
if grep -q -s Microsoft /proc/version; then \
|
||||
echo 'ERROR: AVR flashing cannot be automated within the Windows Subsystem for Linux (WSL) currently. Instead, take the .hex file generated and flash it using AVRDUDE, AVRDUDESS, or XLoader.'; \
|
||||
else \
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <avr/wdt.h>
|
||||
#include <util/delay.h>
|
||||
#include "bootloader.h"
|
||||
#include <avr/boot.h>
|
||||
|
||||
#ifdef PROTOCOL_LUFA
|
||||
#include <LUFA/Drivers/USB/USB.h>
|
||||
|
@ -56,14 +57,17 @@
|
|||
* | Bootloader | 512B | Bootloader | 1KB
|
||||
* 0x7FFF +---------------+ 0x1FFFF +---------------+
|
||||
*/
|
||||
#ifndef BOOTLOADER_SIZE
|
||||
#warning To use bootloader_jump() you need to define BOOTLOADER_SIZE in config.h.
|
||||
#define BOOTLOADER_SIZE 4096
|
||||
|
||||
#define FLASH_SIZE (FLASHEND + 1L)
|
||||
|
||||
#if !defined(BOOTLOADER_SIZE)
|
||||
uint16_t bootloader_start;
|
||||
#endif
|
||||
|
||||
#define FLASH_SIZE (FLASHEND + 1L)
|
||||
#define BOOTLOADER_START (FLASH_SIZE - BOOTLOADER_SIZE)
|
||||
|
||||
#define BOOT_SIZE_256 0b110
|
||||
#define BOOT_SIZE_512 0b100
|
||||
#define BOOT_SIZE_1024 0b010
|
||||
#define BOOT_SIZE_2048 0b000
|
||||
|
||||
/*
|
||||
* Entering the Bootloader via Software
|
||||
|
@ -74,34 +78,62 @@ uint32_t reset_key __attribute__ ((section (".noinit")));
|
|||
|
||||
/* initialize MCU status by watchdog reset */
|
||||
void bootloader_jump(void) {
|
||||
#ifndef CATERINA_BOOTLOADER
|
||||
|
||||
#ifdef PROTOCOL_LUFA
|
||||
USB_Disable();
|
||||
cli();
|
||||
_delay_ms(2000);
|
||||
#endif
|
||||
#if !defined(BOOTLOADER_SIZE)
|
||||
uint8_t high_fuse = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
|
||||
|
||||
#ifdef PROTOCOL_PJRC
|
||||
cli();
|
||||
UDCON = 1;
|
||||
USBCON = (1<<FRZCLK);
|
||||
UCSR1B = 0;
|
||||
_delay_ms(5);
|
||||
#endif
|
||||
if (high_fuse & BOOT_SIZE_256) {
|
||||
bootloader_start = (FLASH_SIZE - 512) >> 1;
|
||||
} else if (high_fuse & BOOT_SIZE_512) {
|
||||
bootloader_start = (FLASH_SIZE - 1024) >> 1;
|
||||
} else if (high_fuse & BOOT_SIZE_1024) {
|
||||
bootloader_start = (FLASH_SIZE - 2048) >> 1;
|
||||
} else {
|
||||
bootloader_start = (FLASH_SIZE - 4096) >> 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BOOTLOADHID_BOOTLOADER
|
||||
// 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
|
||||
// Something like this might work, but it compiled larger than the block above
|
||||
// bootloader_start = FLASH_SIZE - (256 << (~high_fuse & 0b110 >> 1));
|
||||
|
||||
// watchdog reset
|
||||
reset_key = BOOTLOADER_RESET_KEY;
|
||||
wdt_enable(WDTO_250MS);
|
||||
for (;;);
|
||||
|
||||
#else
|
||||
#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
|
||||
|
||||
|
@ -118,83 +150,65 @@ void bootloader_jump(void) {
|
|||
|
||||
while(1) {} // wait for watchdog timer to trigger
|
||||
|
||||
#else // Assume remaining boards are DFU, even if the flag isn't set
|
||||
|
||||
#ifndef __AVR_ATmega32A__ // 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
|
||||
|
||||
}
|
||||
|
||||
#ifdef __AVR_ATmega32A__
|
||||
// MCUSR is actually called MCUCSR in ATmega32A
|
||||
#define MCUSR MCUCSR
|
||||
// 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)
|
||||
{
|
||||
if ((MCUSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
|
||||
reset_key = 0;
|
||||
#ifndef BOOTLOADER_HALFKAY
|
||||
if ((MCUSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
|
||||
reset_key = 0;
|
||||
|
||||
// My custom USBasploader requires this to come up.
|
||||
MCUSR = 0;
|
||||
// My custom USBasploader requires this to come up.
|
||||
MCUSR = 0;
|
||||
|
||||
// Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
|
||||
MCUSR &= ~(1<<WDRF);
|
||||
wdt_disable();
|
||||
// Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
|
||||
MCUSR &= ~(1<<WDRF);
|
||||
wdt_disable();
|
||||
|
||||
// This is compled into 'icall', address should be in word unit, not byte.
|
||||
((void (*)(void))(BOOTLOADER_START/2))();
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* Jumping To The Bootloader
|
||||
* http://www.pjrc.com/teensy/jump_to_bootloader.html
|
||||
*
|
||||
* This method doen't work when using LUFA. idk why.
|
||||
* - needs to initialize more regisers or interrupt setting?
|
||||
*/
|
||||
void bootloader_jump(void) {
|
||||
#ifdef PROTOCOL_LUFA
|
||||
USB_Disable();
|
||||
cli();
|
||||
_delay_ms(2000);
|
||||
#endif
|
||||
|
||||
#ifdef PROTOCOL_PJRC
|
||||
cli();
|
||||
UDCON = 1;
|
||||
USBCON = (1<<FRZCLK);
|
||||
UCSR1B = 0;
|
||||
_delay_ms(5);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize
|
||||
*/
|
||||
#if defined(__AVR_AT90USB162__)
|
||||
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;
|
||||
#elif defined(__AVR_ATmega32U4__)
|
||||
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;
|
||||
#elif defined(__AVR_AT90USB646__)
|
||||
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;
|
||||
#elif defined(__AVR_AT90USB1286__)
|
||||
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;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* USBaspLoader
|
||||
* 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.
|
||||
|
|
20
tmk_core/common/avr/bootloader_size.c
Normal file
20
tmk_core/common/avr/bootloader_size.c
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2017 Jack Humbert
|
||||
//
|
||||
// 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 2 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 <avr/io.h>
|
||||
#include <avr/boot.h>
|
||||
|
||||
// this is not valid C - it's for computing the size available on the chip
|
||||
AVR_SIZE: FLASHEND + 1 - BOOTLOADER_SIZE
|
|
@ -216,6 +216,9 @@ MOVE_DEP = mv -f $(patsubst %.o,%.td,$@) $(patsubst %.o,%.d,$@)
|
|||
|
||||
elf: $(BUILD_DIR)/$(TARGET).elf
|
||||
hex: $(BUILD_DIR)/$(TARGET).hex
|
||||
cphex: hex
|
||||
$(SILENT) || printf "Copying $(TARGET).hex to qmk_firmware folder" | $(AWK_CMD)
|
||||
$(COPY) $(BUILD_DIR)/$(TARGET).hex $(TARGET).hex && $(PRINT_OK)
|
||||
eep: $(BUILD_DIR)/$(TARGET).eep
|
||||
lss: $(BUILD_DIR)/$(TARGET).lss
|
||||
sym: $(BUILD_DIR)/$(TARGET).sym
|
||||
|
@ -223,19 +226,17 @@ LIBNAME=lib$(TARGET).a
|
|||
lib: $(LIBNAME)
|
||||
|
||||
# Display size of file.
|
||||
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
|
||||
HEXSIZE = $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex
|
||||
#ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf
|
||||
ELFSIZE = $(SIZE) $(BUILD_DIR)/$(TARGET).elf
|
||||
|
||||
sizebefore:
|
||||
@if test -f $(TARGET).hex; then $(SECHO) $(MSG_SIZE_BEFORE); $(SILENT) || $(HEXSIZE); \
|
||||
@if test -f $(BUILD_DIR)/$(TARGET).hex; then $(SECHO) $(MSG_SIZE_BEFORE); $(SILENT) || $(HEXSIZE); \
|
||||
2>/dev/null; $(SECHO); fi
|
||||
|
||||
sizeafter: $(BUILD_DIR)/$(TARGET).hex
|
||||
@if test -f $(TARGET).hex; then $(SECHO); $(SECHO) $(MSG_SIZE_AFTER); $(SILENT) || $(HEXSIZE); \
|
||||
@if test -f $(BUILD_DIR)/$(TARGET).hex; then $(SECHO); $(SECHO) $(MSG_SIZE_AFTER); $(SILENT) || $(HEXSIZE); \
|
||||
2>/dev/null; $(SECHO); fi
|
||||
# test file sizes eventually
|
||||
# @if [[ $($(SIZE) --target=$(FORMAT) $(TARGET).hex | $(AWK) 'NR==2 {print "0x"$5}') -gt 0x200 ]]; then $(SECHO) "File is too big!"; fi
|
||||
|
||||
# Display compiler version information.
|
||||
gccversion :
|
||||
|
@ -249,8 +250,6 @@ gccversion :
|
|||
@if $(AUTOGEN); then \
|
||||
$(SILENT) || printf "Copying $(TARGET).hex to keymaps/$(KEYMAP)/$(TARGET).hex\n"; \
|
||||
$(COPY) $@ $(KEYMAP_PATH)/$(TARGET).hex; \
|
||||
else \
|
||||
$(COPY) $@ $(TARGET).hex; \
|
||||
fi
|
||||
|
||||
%.eep: %.elf
|
||||
|
@ -371,6 +370,14 @@ show_path:
|
|||
@echo SRC=$(SRC)
|
||||
@echo OBJ=$(OBJ)
|
||||
|
||||
check-size:
|
||||
$(eval MAX_SIZE=$(shell n=`avr-gcc -E -mmcu=$(MCU) $(CFLAGS) $(OPT_DEFS) tmk_core/common/avr/bootloader_size.c 2> /dev/null | grep -oP "(?<=AVR_SIZE: ).+"`; echo $$(($$n)) || echo 0))
|
||||
$(eval CURRENT_SIZE=$(shell if [ -f $(BUILD_DIR)/$(TARGET).hex ]; then $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex | $(AWK) 'NR==2 {print $$4}'; else printf 0; fi))
|
||||
if [ $(MAX_SIZE) -gt 0 ] && [ $(CURRENT_SIZE) -gt 0 ]; then \
|
||||
$(SILENT) || printf "$(MSG_CHECK_FILESIZE)" | $(AWK_CMD); \
|
||||
if [ $(CURRENT_SIZE) -gt $(MAX_SIZE) ]; then $(PRINT_WARNING_PLAIN); $(SILENT) || printf " * $(MSG_FILE_TOO_BIG)" ; else $(PRINT_OK); $(SILENT) || printf " * $(MSG_FILE_JUST_RIGHT)"; fi \
|
||||
fi
|
||||
|
||||
# Create build directory
|
||||
$(shell mkdir -p $(BUILD_DIR) 2>/dev/null)
|
||||
|
||||
|
@ -385,4 +392,4 @@ $(eval $(foreach OUTPUT,$(OUTPUTS),$(shell mkdir -p $(OUTPUT) 2>/dev/null)))
|
|||
.PHONY : all finish sizebefore sizeafter qmkversion \
|
||||
gccversion build elf hex eep lss sym coff extcoff \
|
||||
clean clean_list debug gdb-config show_path \
|
||||
program teensy dfu flip dfu-ee flip-ee dfu-start
|
||||
program teensy dfu flip dfu-ee flip-ee dfu-start
|
Loading…
Add table
Add a link
Reference in a new issue