diff options
Diffstat (limited to 'platforms/avr')
| -rw-r--r-- | platforms/avr/bootloader.c | 293 | ||||
| -rw-r--r-- | platforms/avr/bootloaders/bootloadhid.c | 33 | ||||
| -rw-r--r-- | platforms/avr/bootloaders/caterina.c | 39 | ||||
| -rw-r--r-- | platforms/avr/bootloaders/dfu.c | 52 | ||||
| -rw-r--r-- | platforms/avr/bootloaders/halfkay.c | 128 | ||||
| -rw-r--r-- | platforms/avr/bootloaders/none.c | 19 | ||||
| -rw-r--r-- | platforms/avr/bootloaders/usbasploader.c | 56 | ||||
| -rw-r--r-- | platforms/avr/drivers/i2c_master.c | 7 | ||||
| -rw-r--r-- | platforms/avr/drivers/serial.c | 7 | ||||
| -rw-r--r-- | platforms/avr/gpio.h | 17 | 
10 files changed, 336 insertions, 315 deletions
| 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/avr/bootloaders/none.c b/platforms/avr/bootloaders/none.c new file mode 100644 index 0000000000..624fbe242a --- /dev/null +++ b/platforms/avr/bootloaders/none.c @@ -0,0 +1,19 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include "bootloader.h" + +__attribute__((weak)) void bootloader_jump(void) {} 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)) | 
