diff options
Diffstat (limited to 'platforms')
40 files changed, 987 insertions, 618 deletions
| diff --git a/platforms/arm_atsam/bootloader.c b/platforms/arm_atsam/bootloaders/md_boot.c index 9015b00aab..e7508ffe51 100644 --- a/platforms/arm_atsam/bootloader.c +++ b/platforms/arm_atsam/bootloaders/md_boot.c @@ -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) {  #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,34 @@ 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 + +        while (1) +            ;  // Won't get here      } -#endif +} +#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 diff --git a/platforms/arm_atsam/gpio.h b/platforms/arm_atsam/gpio.h index 915ed0ef4f..a42aaff54d 100644 --- a/platforms/arm_atsam/gpio.h +++ b/platforms/arm_atsam/gpio.h @@ -22,9 +22,9 @@  typedef uint8_t pin_t; -#define SAMD_PORT(pin) ((pin & 0x20) >> 5) -#define SAMD_PIN(pin) (pin & 0x1f) -#define SAMD_PIN_MASK(pin) (1 << (pin & 0x1f)) +#define SAMD_PORT(pin) (((pin)&0x20) >> 5) +#define SAMD_PIN(pin) ((pin)&0x1f) +#define SAMD_PIN_MASK(pin) (1 << ((pin)&0x1f))  #define setPinInput(pin)                                                                 \      do {                                                                                 \ @@ -48,12 +48,16 @@ typedef uint8_t pin_t;          PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.PULLEN = 1;                  \      } while (0) -#define setPinOutput(pin)                                            \ +#define setPinOutputPushPull(pin)                                    \      do {                                                             \          PORT->Group[SAMD_PORT(pin)].DIRSET.reg = SAMD_PIN_MASK(pin); \          PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \      } while (0) +#define setPinOutputOpenDrain(pin) _Static_assert(0, "arm_atsam platform does not implement an open-drain output") + +#define setPinOutput(pin) setPinOutputPushPull(pin) +  #define writePinHigh(pin)                                            \      do {                                                             \          PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \ diff --git a/platforms/avr/bootloader.c b/platforms/avr/bootloader.c deleted file mode 100644 index c0272903b8..0000000000 --- a/platforms/avr/bootloader.c +++ /dev/null @@ -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 -} diff --git a/platforms/avr/bootloaders/bootloadhid.c b/platforms/avr/bootloaders/bootloadhid.c new file mode 100644 index 0000000000..ae58760d7d --- /dev/null +++ b/platforms/avr/bootloaders/bootloadhid.c @@ -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 <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 (;;) +        ; +} diff --git a/platforms/avr/bootloaders/caterina.c b/platforms/avr/bootloaders/caterina.c new file mode 100644 index 0000000000..82a16a3765 --- /dev/null +++ b/platforms/avr/bootloaders/caterina.c @@ -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) { +    } +} diff --git a/platforms/avr/bootloaders/dfu.c b/platforms/avr/bootloaders/dfu.c new file mode 100644 index 0000000000..cb42821a93 --- /dev/null +++ b/platforms/avr/bootloaders/dfu.c @@ -0,0 +1,52 @@ +/* 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))(); +    } +} diff --git a/platforms/avr/bootloaders/halfkay.c b/platforms/avr/bootloaders/halfkay.c new file mode 100644 index 0000000000..6ce2e19114 --- /dev/null +++ b/platforms/avr/bootloaders/halfkay.c @@ -0,0 +1,128 @@ +/* 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 +} diff --git a/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/config.h b/platforms/avr/bootloaders/none.c index 39ce627e77..624fbe242a 100644 --- a/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/config.h +++ b/platforms/avr/bootloaders/none.c @@ -1,8 +1,8 @@ -/* Copyright 2018-2020 Nick Brassel (@tzarc) +/* 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 2 of the License, or + * 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, @@ -14,10 +14,6 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up here (page 175): - * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf - * This also requires a patch to chibios: - *  <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 +#include "bootloader.h" + +__attribute__((weak)) void bootloader_jump(void) {} diff --git a/platforms/avr/bootloaders/usbasploader.c b/platforms/avr/bootloaders/usbasploader.c new file mode 100644 index 0000000000..008bd16069 --- /dev/null +++ b/platforms/avr/bootloaders/usbasploader.c @@ -0,0 +1,56 @@ +/* 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)); +} diff --git a/platforms/avr/drivers/i2c_master.c b/platforms/avr/drivers/i2c_master.c index 111b55d6b0..d4024378ca 100644 --- a/platforms/avr/drivers/i2c_master.c +++ b/platforms/avr/drivers/i2c_master.c @@ -32,6 +32,9 @@  #    define I2C_START_RETRY_COUNT 20  #endif  // I2C_START_RETRY_COUNT +#define I2C_ACTION_READ 0x01 +#define I2C_ACTION_WRITE 0x00 +  #define TWBR_val (((F_CPU / F_SCL) - 16) / 2)  #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) @@ -154,7 +157,7 @@ int16_t i2c_read_nack(uint16_t timeout) {  }  i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) { -    i2c_status_t status = i2c_start(address | I2C_WRITE, timeout); +    i2c_status_t status = i2c_start(address | I2C_ACTION_WRITE, timeout);      for (uint16_t i = 0; i < length && status >= 0; i++) {          status = i2c_write(data[i], timeout); @@ -166,7 +169,7 @@ i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length,  }  i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { -    i2c_status_t status = i2c_start(address | I2C_READ, timeout); +    i2c_status_t status = i2c_start(address | I2C_ACTION_READ, timeout);      for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) {          status = i2c_read_ack(timeout); diff --git a/platforms/avr/drivers/serial.c b/platforms/avr/drivers/serial.c index 9a7345a53d..ab0b52afd1 100644 --- a/platforms/avr/drivers/serial.c +++ b/platforms/avr/drivers/serial.c @@ -16,6 +16,7 @@  #include <util/delay.h>  #include <stddef.h>  #include <stdbool.h> +#include "gpio.h"  #include "serial.h"  #ifdef SOFT_SERIAL_PIN @@ -119,12 +120,6 @@  #        error invalid SOFT_SERIAL_PIN value  #    endif -#    define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) -#    define setPinOutput(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF)) -#    define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) -#    define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF)) -#    define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF))) -  #    define ALWAYS_INLINE __attribute__((always_inline))  #    define NO_INLINE __attribute__((noinline))  #    define _delay_sub_us(x) __builtin_avr_delay_cycles(x) diff --git a/platforms/avr/gpio.h b/platforms/avr/gpio.h index e9be68491d..95f15c28dc 100644 --- a/platforms/avr/gpio.h +++ b/platforms/avr/gpio.h @@ -25,7 +25,9 @@ typedef uint8_t pin_t;  #define setPinInput(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))  #define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF))  #define setPinInputLow(pin) _Static_assert(0, "AVR processors cannot implement an input as pull low") -#define setPinOutput(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF)) +#define setPinOutputPushPull(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF)) +#define setPinOutputOpenDrain(pin) _Static_assert(0, "AVR platform does not implement an open-drain output") +#define setPinOutput(pin) setPinOutputPushPull(pin)  #define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF))  #define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF)) @@ -34,16 +36,3 @@ typedef uint8_t pin_t;  #define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF)))  #define togglePin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF)) - -/* Operation of GPIO by port. */ - -typedef uint8_t port_data_t; - -#define readPort(port) PINx_ADDRESS(port) - -#define setPortBitInput(port, bit) (DDRx_ADDRESS(port) &= ~_BV((bit)&0xF), PORTx_ADDRESS(port) &= ~_BV((bit)&0xF)) -#define setPortBitInputHigh(port, bit) (DDRx_ADDRESS(port) &= ~_BV((bit)&0xF), PORTx_ADDRESS(port) |= _BV((bit)&0xF)) -#define setPortBitOutput(port, bit) (DDRx_ADDRESS(port) |= _BV((bit)&0xF)) - -#define writePortBitLow(port, bit) (PORTx_ADDRESS(port) &= ~_BV((bit)&0xF)) -#define writePortBitHigh(port, bit) (PORTx_ADDRESS(port) |= _BV((bit)&0xF)) diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/bootloader_defs.h b/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/bootloader_defs.h deleted file mode 100644 index 4da3d39a32..0000000000 --- a/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/bootloader_defs.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up here: - * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/bootloader_defs.h b/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/bootloader_defs.h deleted file mode 100644 index 4da3d39a32..0000000000 --- a/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/bootloader_defs.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up here: - * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 diff --git a/platforms/chibios/boards/GENERIC_STM32_F042X6/configs/bootloader_defs.h b/platforms/chibios/boards/GENERIC_STM32_F042X6/configs/bootloader_defs.h deleted file mode 100644 index 25113425a6..0000000000 --- a/platforms/chibios/boards/GENERIC_STM32_F042X6/configs/bootloader_defs.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up here: - * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFFC400 diff --git a/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/bootloader_defs.h b/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/bootloader_defs.h deleted file mode 100644 index dccd0fa5d1..0000000000 --- a/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/bootloader_defs.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up here (page 175): - * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFFC800 diff --git a/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/bootloader_defs.h b/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/bootloader_defs.h deleted file mode 100644 index 87ac7b10dc..0000000000 --- a/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/bootloader_defs.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up here: - * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFFD800 diff --git a/platforms/chibios/boards/GENERIC_STM32_F405XG/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_F405XG/configs/config.h index cc52a953ed..90a41326a1 100644 --- a/platforms/chibios/boards/GENERIC_STM32_F405XG/configs/config.h +++ b/platforms/chibios/boards/GENERIC_STM32_F405XG/configs/config.h @@ -17,7 +17,7 @@  /* Address for jumping to bootloader on STM32 chips. */  /* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606.   */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 +  #ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP  #    define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE  #endif diff --git a/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/config.h index cc52a953ed..90a41326a1 100644 --- a/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/config.h +++ b/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/config.h @@ -17,7 +17,7 @@  /* Address for jumping to bootloader on STM32 chips. */  /* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606.   */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 +  #ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP  #    define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE  #endif diff --git a/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/config.h index cc52a953ed..90a41326a1 100644 --- a/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/config.h +++ b/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/config.h @@ -17,7 +17,7 @@  /* Address for jumping to bootloader on STM32 chips. */  /* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606.   */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 +  #ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP  #    define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE  #endif diff --git a/platforms/chibios/boards/GENERIC_STM32_L412XB/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_L412XB/configs/config.h index c27c61b19a..fc9055ccfb 100644 --- a/platforms/chibios/boards/GENERIC_STM32_L412XB/configs/config.h +++ b/platforms/chibios/boards/GENERIC_STM32_L412XB/configs/config.h @@ -17,7 +17,6 @@  /* Address for jumping to bootloader on STM32 chips. */  /* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606.   */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000  #define PAL_STM32_OSPEED_HIGHEST PAL_STM32_OSPEED_HIGH diff --git a/platforms/chibios/boards/GENERIC_STM32_L432XC/board/board.mk b/platforms/chibios/boards/GENERIC_STM32_L432XC/board/board.mk new file mode 100644 index 0000000000..1250385eb8 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_L432XC/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC  += $(BOARDINC) diff --git a/platforms/chibios/boards/GENERIC_STM32_L432XC/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_L432XC/configs/config.h new file mode 100644 index 0000000000..b1838b30a8 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_L432XC/configs/config.h @@ -0,0 +1,10 @@ +// Copyright 2021 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +// Fixup equivalent usages within QMK as the base board definitions only go up to high +#define PAL_STM32_OSPEED_HIGHEST PAL_STM32_OSPEED_HIGH + +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +#    define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/boards/GENERIC_STM32_L432XC/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_L432XC/configs/mcuconf.h new file mode 100644 index 0000000000..707134d49e --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_L432XC/configs/mcuconf.h @@ -0,0 +1,267 @@ +/* +    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + +    Licensed under the Apache License, Version 2.0 (the "License"); +    you may not use this file except in compliance with the License. +    You may obtain a copy of the License at + +        http://www.apache.org/licenses/LICENSE-2.0 + +    Unless required by applicable law or agreed to in writing, software +    distributed under the License is distributed on an "AS IS" BASIS, +    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +    See the License for the specific language governing permissions and +    limitations under the License. +*/ + +/* + * STM32L4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0       Lowest...Highest. + * + * DMA priorities: + * 0...3        Lowest...Highest. + */ + +#ifndef MCUCONF_H +#define MCUCONF_H + +#define STM32L4xx_MCUCONF +#define STM32L432_MCUCONF +#define STM32L433_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT                       FALSE +#define STM32_VOS                           STM32_VOS_RANGE1 +#define STM32_PVD_ENABLE                    FALSE +#define STM32_PLS                           STM32_PLS_LEV0 +#define STM32_HSI16_ENABLED                 TRUE +#define STM32_HSI48_ENABLED                 TRUE +#define STM32_LSI_ENABLED                   TRUE +#define STM32_HSE_ENABLED                   FALSE +#define STM32_LSE_ENABLED                   FALSE +#define STM32_MSIPLL_ENABLED                FALSE +#define STM32_MSIRANGE                      STM32_MSIRANGE_4M +#define STM32_MSISRANGE                     STM32_MSISRANGE_4M +#define STM32_SW                            STM32_SW_PLL +#define STM32_PLLSRC                        STM32_PLLSRC_HSI16 +#define STM32_PLLM_VALUE                    1 +#define STM32_PLLN_VALUE                    10 +#define STM32_PLLPDIV_VALUE                 0 +#define STM32_PLLP_VALUE                    7 +#define STM32_PLLQ_VALUE                    2 +#define STM32_PLLR_VALUE                    2 +#define STM32_HPRE                          STM32_HPRE_DIV1 +#define STM32_PPRE1                         STM32_PPRE1_DIV1 +#define STM32_PPRE2                         STM32_PPRE2_DIV1 +#define STM32_STOPWUCK                      STM32_STOPWUCK_MSI +#define STM32_MCOSEL                        STM32_MCOSEL_NOCLOCK +#define STM32_MCOPRE                        STM32_MCOPRE_DIV1 +#define STM32_LSCOSEL                       STM32_LSCOSEL_NOCLOCK +#define STM32_PLLSAI1N_VALUE                24 +#define STM32_PLLSAI1PDIV_VALUE             0 +#define STM32_PLLSAI1P_VALUE                7 +#define STM32_PLLSAI1Q_VALUE                2 +#define STM32_PLLSAI1R_VALUE                2 + +/* + * Peripherals clock sources. + */ +#define STM32_USART1SEL                     STM32_USART1SEL_SYSCLK +#define STM32_USART2SEL                     STM32_USART2SEL_SYSCLK +#define STM32_LPUART1SEL                    STM32_LPUART1SEL_SYSCLK +#define STM32_I2C1SEL                       STM32_I2C1SEL_SYSCLK +#define STM32_I2C3SEL                       STM32_I2C3SEL_SYSCLK +#define STM32_LPTIM1SEL                     STM32_LPTIM1SEL_PCLK1 +#define STM32_LPTIM2SEL                     STM32_LPTIM2SEL_PCLK1 +#define STM32_SAI1SEL                       STM32_SAI1SEL_OFF +#define STM32_CLK48SEL                      STM32_CLK48SEL_HSI48 +#define STM32_ADCSEL                        STM32_ADCSEL_SYSCLK +#define STM32_SWPMI1SEL                     STM32_SWPMI1SEL_PCLK1 +#define STM32_RTCSEL                        STM32_RTCSEL_LSI + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY            6 +#define STM32_IRQ_EXTI1_PRIORITY            6 +#define STM32_IRQ_EXTI2_PRIORITY            6 +#define STM32_IRQ_EXTI3_PRIORITY            6 +#define STM32_IRQ_EXTI4_PRIORITY            6 +#define STM32_IRQ_EXTI5_9_PRIORITY          6 +#define STM32_IRQ_EXTI10_15_PRIORITY        6 +#define STM32_IRQ_EXTI1635_38_PRIORITY      6 +#define STM32_IRQ_EXTI18_PRIORITY           6 +#define STM32_IRQ_EXTI19_PRIORITY           6 +#define STM32_IRQ_EXTI20_PRIORITY           6 +#define STM32_IRQ_EXTI21_22_PRIORITY        15 + +#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY   7 +#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY    7 +#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 +#define STM32_IRQ_TIM1_CC_PRIORITY          7 +#define STM32_IRQ_TIM2_PRIORITY             7 +#define STM32_IRQ_TIM6_PRIORITY             7 +#define STM32_IRQ_TIM7_PRIORITY             7 + +#define STM32_IRQ_USART1_PRIORITY           12 +#define STM32_IRQ_USART2_PRIORITY           12 +#define STM32_IRQ_LPUART1_PRIORITY          12 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_COMPACT_SAMPLES           FALSE +#define STM32_ADC_USE_ADC1                  FALSE +#define STM32_ADC_ADC1_DMA_STREAM           STM32_DMA_STREAM_ID(1, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY         2 +#define STM32_ADC_ADC12_IRQ_PRIORITY        5 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY     5 +#define STM32_ADC_ADC123_CLOCK_MODE         ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC_ADC123_PRESC              ADC_CCR_PRESC_DIV2 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1                  FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY         11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE                 FALSE +#define STM32_DAC_USE_DAC1_CH1              FALSE +#define STM32_DAC_USE_DAC1_CH2              FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY     10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY     10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY     2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY     2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM       STM32_DMA_STREAM_ID(2, 4) +#define STM32_DAC_DAC1_CH2_DMA_STREAM       STM32_DMA_STREAM_ID(1, 4) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1                  FALSE +#define STM32_GPT_USE_TIM2                  FALSE +#define STM32_GPT_USE_TIM6                  FALSE +#define STM32_GPT_USE_TIM7                  FALSE +#define STM32_GPT_USE_TIM15                 FALSE +#define STM32_GPT_USE_TIM16                 FALSE + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1                  FALSE +#define STM32_I2C_USE_I2C3                  FALSE +#define STM32_I2C_BUSY_TIMEOUT              50 +#define STM32_I2C_I2C1_RX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C3_RX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2C_I2C3_TX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C1_IRQ_PRIORITY         5 +#define STM32_I2C_I2C3_IRQ_PRIORITY         5 +#define STM32_I2C_I2C1_DMA_PRIORITY         3 +#define STM32_I2C_I2C3_DMA_PRIORITY         3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp)      osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1                  FALSE +#define STM32_ICU_USE_TIM2                  FALSE +#define STM32_ICU_USE_TIM15                 FALSE +#define STM32_ICU_USE_TIM16                 FALSE + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED              FALSE +#define STM32_PWM_USE_TIM1                  FALSE +#define STM32_PWM_USE_TIM2                  FALSE +#define STM32_PWM_USE_TIM15                 FALSE +#define STM32_PWM_USE_TIM16                 FALSE + +/* + * RTC driver system settings. + */ +#define STM32_RTC_PRESA_VALUE               32 +#define STM32_RTC_PRESS_VALUE               1024 +#define STM32_RTC_CR_INIT                   0 +#define STM32_RTC_TAMPCR_INIT               0 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1             FALSE +#define STM32_SERIAL_USE_USART2             FALSE +#define STM32_SERIAL_USE_LPUART1            FALSE +#define STM32_SERIAL_USART1_PRIORITY        12 +#define STM32_SERIAL_USART2_PRIORITY        12 +#define STM32_SERIAL_LPUART1_PRIORITY       12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1                  FALSE +#define STM32_SPI_USE_SPI3                  FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM        STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI1_TX_DMA_STREAM        STM32_DMA_STREAM_ID(2, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM        STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM        STM32_DMA_STREAM_ID(2, 2) +#define STM32_SPI_SPI1_DMA_PRIORITY         1 +#define STM32_SPI_SPI3_DMA_PRIORITY         1 +#define STM32_SPI_SPI1_IRQ_PRIORITY         10 +#define STM32_SPI_SPI3_IRQ_PRIORITY         10 +#define STM32_SPI_DMA_ERROR_HOOK(spip)      osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY               8 +#define STM32_ST_USE_TIMER                  2 + +/* + * TRNG driver system settings. + */ +#define STM32_TRNG_USE_RNG1                 FALSE + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1               FALSE +#define STM32_UART_USE_USART2               FALSE +#define STM32_UART_USART1_RX_DMA_STREAM     STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_TX_DMA_STREAM     STM32_DMA_STREAM_ID(2, 6) +#define STM32_UART_USART2_RX_DMA_STREAM     STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM     STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_DMA_ERROR_HOOK(uartp)    osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_USB1                  TRUE +#define STM32_USB_LOW_POWER_ON_SUSPEND      FALSE +#define STM32_USB_USB1_HP_IRQ_PRIORITY      13 +#define STM32_USB_USB1_LP_IRQ_PRIORITY      14 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG                  FALSE + +/* + * WSPI driver system settings. + */ +#define STM32_WSPI_USE_QUADSPI1             FALSE +#define STM32_WSPI_QUADSPI1_DMA_STREAM      STM32_DMA_STREAM_ID(2, 7) +#define STM32_WSPI_QUADSPI1_PRESCALER_VALUE 1 + +#endif /* MCUCONF_H */ diff --git a/platforms/chibios/boards/GENERIC_STM32_L433XC/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_L433XC/configs/config.h index c27c61b19a..fc9055ccfb 100644 --- a/platforms/chibios/boards/GENERIC_STM32_L433XC/configs/config.h +++ b/platforms/chibios/boards/GENERIC_STM32_L433XC/configs/config.h @@ -17,7 +17,6 @@  /* Address for jumping to bootloader on STM32 chips. */  /* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606.   */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000  #define PAL_STM32_OSPEED_HIGHEST PAL_STM32_OSPEED_HIGH diff --git a/platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/bootloader_defs.h b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/bootloader_defs.h deleted file mode 100644 index c929d2ad03..0000000000 --- a/platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/bootloader_defs.h +++ /dev/null @@ -1,12 +0,0 @@ -/* Address for jumping to bootloader on WB32 chips. */ -/* It is chip dependent, the correct number can be looked up here: - * http://www.westberrytech.com/down/mcu/data/WB32F3G71xx_rm.pdf - */ -#ifndef WB32_BOOTLOADER_ADDRESS -#    undef STM32_BOOTLOADER_ADDRESS -#    define WB32_BOOTLOADER_ADDRESS 0x1FFFE000 -#    define STM32_BOOTLOADER_ADDRESS WB32_BOOTLOADER_ADDRESS -#else -#    undef STM32_BOOTLOADER_ADDRESS -#    define STM32_BOOTLOADER_ADDRESS WB32_BOOTLOADER_ADDRESS -#endif diff --git a/platforms/chibios/boards/QMK_PROTON_C/configs/bootloader_defs.h b/platforms/chibios/boards/QMK_PROTON_C/configs/bootloader_defs.h deleted file mode 100644 index 3b0e9d20a6..0000000000 --- a/platforms/chibios/boards/QMK_PROTON_C/configs/bootloader_defs.h +++ /dev/null @@ -1,7 +0,0 @@ -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up here: - * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf - * This also requires a patch to chibios: - *  <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFFD800 diff --git a/platforms/chibios/bootloader.c b/platforms/chibios/bootloader.c deleted file mode 100644 index 58212948b0..0000000000 --- a/platforms/chibios/bootloader.c +++ /dev/null @@ -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 diff --git a/platforms/chibios/bootloaders/gd32v_dfu.c b/platforms/chibios/bootloaders/gd32v_dfu.c new file mode 100644 index 0000000000..baa7d1f882 --- /dev/null +++ b/platforms/chibios/bootloaders/gd32v_dfu.c @@ -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> +#include <hal.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) {} diff --git a/platforms/chibios/bootloaders/halfkay.c b/platforms/chibios/bootloaders/halfkay.c new file mode 100644 index 0000000000..168c2abc23 --- /dev/null +++ b/platforms/chibios/bootloaders/halfkay.c @@ -0,0 +1,25 @@ +/* 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); +} diff --git a/platforms/chibios/bootloaders/kiibohd.c b/platforms/chibios/bootloaders/kiibohd.c new file mode 100644 index 0000000000..911e807092 --- /dev/null +++ b/platforms/chibios/bootloaders/kiibohd.c @@ -0,0 +1,32 @@ +/* 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; +} diff --git a/platforms/chibios/bootloaders/none.c b/platforms/chibios/bootloaders/none.c new file mode 100644 index 0000000000..8379d35abf --- /dev/null +++ b/platforms/chibios/bootloaders/none.c @@ -0,0 +1,23 @@ +/* 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" + +#pragma message "Unknown bootloader set, you may not be able to enter bootloader using software reset" + +__attribute__((weak)) void bootloader_jump(void) {} + +__attribute__((weak)) void enter_bootloader_mode_if_requested(void) {} diff --git a/platforms/chibios/bootloaders/stm32_dfu.c b/platforms/chibios/bootloaders/stm32_dfu.c new file mode 100644 index 0000000000..0a113570f7 --- /dev/null +++ b/platforms/chibios/bootloaders/stm32_dfu.c @@ -0,0 +1,94 @@ +/* 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 diff --git a/platforms/chibios/bootloaders/stm32duino.c b/platforms/chibios/bootloaders/stm32duino.c new file mode 100644 index 0000000000..dd1d551fa9 --- /dev/null +++ b/platforms/chibios/bootloaders/stm32duino.c @@ -0,0 +1,21 @@ +/* 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(); } diff --git a/platforms/chibios/bootloaders/tinyuf2.c b/platforms/chibios/bootloaders/tinyuf2.c new file mode 100644 index 0000000000..9ffca5dec8 --- /dev/null +++ b/platforms/chibios/bootloaders/tinyuf2.c @@ -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 <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) {} diff --git a/platforms/chibios/drivers/i2c_master.c b/platforms/chibios/drivers/i2c_master.c index 43591d56f8..4a5d4760d0 100644 --- a/platforms/chibios/drivers/i2c_master.c +++ b/platforms/chibios/drivers/i2c_master.c @@ -27,8 +27,67 @@  #include "quantum.h"  #include "i2c_master.h"  #include <string.h> +#include <ch.h>  #include <hal.h> +#ifndef I2C1_SCL_PIN +#    define I2C1_SCL_PIN B6 +#endif +#ifndef I2C1_SDA_PIN +#    define I2C1_SDA_PIN B7 +#endif + +#ifdef USE_I2CV1 +#    ifndef I2C1_OPMODE +#        define I2C1_OPMODE OPMODE_I2C +#    endif +#    ifndef I2C1_CLOCK_SPEED +#        define I2C1_CLOCK_SPEED 100000 /* 400000 */ +#    endif +#    ifndef I2C1_DUTY_CYCLE +#        define I2C1_DUTY_CYCLE STD_DUTY_CYCLE /* FAST_DUTY_CYCLE_2 */ +#    endif +#else +// The default timing values below configures the I2C clock to 400khz assuming a 72Mhz clock +// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html +#    ifndef I2C1_TIMINGR_PRESC +#        define I2C1_TIMINGR_PRESC 0U +#    endif +#    ifndef I2C1_TIMINGR_SCLDEL +#        define I2C1_TIMINGR_SCLDEL 7U +#    endif +#    ifndef I2C1_TIMINGR_SDADEL +#        define I2C1_TIMINGR_SDADEL 0U +#    endif +#    ifndef I2C1_TIMINGR_SCLH +#        define I2C1_TIMINGR_SCLH 38U +#    endif +#    ifndef I2C1_TIMINGR_SCLL +#        define I2C1_TIMINGR_SCLL 129U +#    endif +#endif + +#ifndef I2C_DRIVER +#    define I2C_DRIVER I2CD1 +#endif + +#ifdef USE_GPIOV1 +#    ifndef I2C1_SCL_PAL_MODE +#        define I2C1_SCL_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN +#    endif +#    ifndef I2C1_SDA_PAL_MODE +#        define I2C1_SDA_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN +#    endif +#else +// The default PAL alternate modes are used to signal that the pins are used for I2C +#    ifndef I2C1_SCL_PAL_MODE +#        define I2C1_SCL_PAL_MODE 4 +#    endif +#    ifndef I2C1_SDA_PAL_MODE +#        define I2C1_SDA_PAL_MODE 4 +#    endif +#endif +  static uint8_t i2c_address;  static const I2CConfig i2cconfig = { diff --git a/platforms/chibios/drivers/i2c_master.h b/platforms/chibios/drivers/i2c_master.h index 5f082e9d1e..deee7ecc08 100644 --- a/platforms/chibios/drivers/i2c_master.h +++ b/platforms/chibios/drivers/i2c_master.h @@ -24,66 +24,7 @@   */  #pragma once -#include <ch.h> -#include <hal.h> - -#ifndef I2C1_SCL_PIN -#    define I2C1_SCL_PIN B6 -#endif -#ifndef I2C1_SDA_PIN -#    define I2C1_SDA_PIN B7 -#endif - -#ifdef USE_I2CV1 -#    ifndef I2C1_OPMODE -#        define I2C1_OPMODE OPMODE_I2C -#    endif -#    ifndef I2C1_CLOCK_SPEED -#        define I2C1_CLOCK_SPEED 100000 /* 400000 */ -#    endif -#    ifndef I2C1_DUTY_CYCLE -#        define I2C1_DUTY_CYCLE STD_DUTY_CYCLE /* FAST_DUTY_CYCLE_2 */ -#    endif -#else -// The default timing values below configures the I2C clock to 400khz assuming a 72Mhz clock -// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html -#    ifndef I2C1_TIMINGR_PRESC -#        define I2C1_TIMINGR_PRESC 0U -#    endif -#    ifndef I2C1_TIMINGR_SCLDEL -#        define I2C1_TIMINGR_SCLDEL 7U -#    endif -#    ifndef I2C1_TIMINGR_SDADEL -#        define I2C1_TIMINGR_SDADEL 0U -#    endif -#    ifndef I2C1_TIMINGR_SCLH -#        define I2C1_TIMINGR_SCLH 38U -#    endif -#    ifndef I2C1_TIMINGR_SCLL -#        define I2C1_TIMINGR_SCLL 129U -#    endif -#endif - -#ifndef I2C_DRIVER -#    define I2C_DRIVER I2CD1 -#endif - -#ifdef USE_GPIOV1 -#    ifndef I2C1_SCL_PAL_MODE -#        define I2C1_SCL_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN -#    endif -#    ifndef I2C1_SDA_PAL_MODE -#        define I2C1_SDA_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN -#    endif -#else -// The default PAL alternate modes are used to signal that the pins are used for I2C -#    ifndef I2C1_SCL_PAL_MODE -#        define I2C1_SCL_PAL_MODE 4 -#    endif -#    ifndef I2C1_SDA_PAL_MODE -#        define I2C1_SDA_PAL_MODE 4 -#    endif -#endif +#include <stdint.h>  typedef int16_t i2c_status_t; diff --git a/platforms/chibios/gpio.h b/platforms/chibios/gpio.h index 4d057f1cab..eb44a18f9c 100644 --- a/platforms/chibios/gpio.h +++ b/platforms/chibios/gpio.h @@ -22,10 +22,12 @@ typedef ioline_t pin_t;  /* Operation of GPIO by pin. */ -#define setPinInput(pin) palSetLineMode(pin, PAL_MODE_INPUT) -#define setPinInputHigh(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLUP) -#define setPinInputLow(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLDOWN) -#define setPinOutput(pin) palSetLineMode(pin, PAL_MODE_OUTPUT_PUSHPULL) +#define setPinInput(pin) palSetLineMode((pin), PAL_MODE_INPUT) +#define setPinInputHigh(pin) palSetLineMode((pin), PAL_MODE_INPUT_PULLUP) +#define setPinInputLow(pin) palSetLineMode((pin), PAL_MODE_INPUT_PULLDOWN) +#define setPinOutputPushPull(pin) palSetLineMode((pin), PAL_MODE_OUTPUT_PUSHPULL) +#define setPinOutputOpenDrain(pin) palSetLineMode((pin), PAL_MODE_OUTPUT_OPENDRAIN) +#define setPinOutput(pin) setPinOutputPushPull(pin)  #define writePinHigh(pin) palSetLine(pin)  #define writePinLow(pin) palClearLine(pin) @@ -34,17 +36,3 @@ typedef ioline_t pin_t;  #define readPin(pin) palReadLine(pin)  #define togglePin(pin) palToggleLine(pin) - -/* Operation of GPIO by port. */ - -typedef uint16_t port_data_t; - -#define readPort(pin) palReadPort(PAL_PORT(pin)) - -#define setPortBitInput(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT) -#define setPortBitInputHigh(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT_PULLUP) -#define setPortBitInputLow(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT_PULLDOWN) -#define setPortBitOutput(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_OUTPUT_PUSHPULL) - -#define writePortBitLow(pin, bit) palClearLine(PAL_LINE(PAL_PORT(pin), bit)) -#define writePortBitHigh(pin, bit) palSetLine(PAL_LINE(PAL_PORT(pin), bit)) diff --git a/platforms/common.mk b/platforms/common.mk index f7a0fc7028..12ab45f823 100644 --- a/platforms/common.mk +++ b/platforms/common.mk @@ -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) diff --git a/platforms/test/bootloader.c b/platforms/test/bootloaders/none.c index 5155d9ff04..5155d9ff04 100644 --- a/platforms/test/bootloader.c +++ b/platforms/test/bootloaders/none.c | 
