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/custom.c | 19 | ||||
-rw-r--r-- | platforms/avr/bootloaders/dfu.c | 52 | ||||
-rw-r--r-- | platforms/avr/bootloaders/halfkay.c | 128 | ||||
-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 | 46 | ||||
-rw-r--r-- | platforms/avr/gpio.h | 17 | ||||
-rw-r--r-- | platforms/avr/suspend.c | 55 |
11 files changed, 356 insertions, 389 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/custom.c b/platforms/avr/bootloaders/custom.c new file mode 100644 index 0000000000..624fbe242a --- /dev/null +++ b/platforms/avr/bootloaders/custom.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/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/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..62908e5875 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) @@ -414,13 +409,7 @@ ISR(SERIAL_PIN_INTERRUPT) { // target recive phase if (trans->initiator2target_buffer_size > 0) { - if (serial_recive_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) { - *trans->status = TRANSACTION_ACCEPTED; - } else { - *trans->status = TRANSACTION_DATA_ERROR; - } - } else { - *trans->status = TRANSACTION_ACCEPTED; + serial_recive_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size); } sync_recv(); // weit initiator output to high @@ -429,19 +418,13 @@ ISR(SERIAL_PIN_INTERRUPT) { ///////// // start transaction by initiator // -// int soft_serial_transaction(int sstd_index) +// bool soft_serial_transaction(int sstd_index) // -// Returns: -// TRANSACTION_END -// TRANSACTION_NO_RESPONSE -// TRANSACTION_DATA_ERROR // this code is very time dependent, so we need to disable interrupts -int soft_serial_transaction(int sstd_index) { - if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR; +bool soft_serial_transaction(int sstd_index) { + if (sstd_index > NUM_TOTAL_TRANSACTIONS) return false; split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; - if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered - cli(); // signal to the target that we want to start a transaction @@ -468,9 +451,8 @@ int soft_serial_transaction(int sstd_index) { // slave failed to pull the line low, assume not present serial_output(); serial_high(); - *trans->status = TRANSACTION_NO_RESPONSE; sei(); - return TRANSACTION_NO_RESPONSE; + return false; } _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT); } @@ -481,9 +463,8 @@ int soft_serial_transaction(int sstd_index) { if (!serial_recive_packet((uint8_t *)split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) { serial_output(); serial_high(); - *trans->status = TRANSACTION_DATA_ERROR; sei(); - return TRANSACTION_DATA_ERROR; + return false; } } @@ -498,19 +479,8 @@ int soft_serial_transaction(int sstd_index) { // always, release the line when not in use sync_send(); - *trans->status = TRANSACTION_END; - sei(); - return TRANSACTION_END; -} - -int soft_serial_get_and_clean_status(int sstd_index) { - split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; - cli(); - int retval = *trans->status; - *trans->status = 0; - ; sei(); - return retval; + return true; } #endif 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/avr/suspend.c b/platforms/avr/suspend.c index b614746e6c..b615979439 100644 --- a/platforms/avr/suspend.c +++ b/platforms/avr/suspend.c @@ -2,12 +2,9 @@ #include <avr/sleep.h> #include <avr/wdt.h> #include <avr/interrupt.h> -#include "matrix.h" -#include "action.h" #include "suspend.h" +#include "action.h" #include "timer.h" -#include "led.h" -#include "host.h" #ifdef PROTOCOL_LUFA # include "lufa.h" @@ -16,19 +13,6 @@ # include "vusb.h" #endif -/** \brief Suspend idle - * - * FIXME: needs doc - */ -void suspend_idle(uint8_t time) { - cli(); - set_sleep_mode(SLEEP_MODE_IDLE); - sleep_enable(); - sei(); - sleep_cpu(); - sleep_disable(); -} - // TODO: This needs some cleanup #if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect) @@ -91,6 +75,18 @@ static void power_down(uint8_t wdto) { // Disable watchdog after sleep wdt_disable(); } + +/* watchdog timeout */ +ISR(WDT_vect) { + // compensate timer for sleep + switch (wdt_timeout) { + case WDTO_15MS: + timer_count += 15 + 2; // WDTO_15MS + 2(from observation) + break; + default:; + } +} + #endif /** \brief Suspend power down @@ -115,18 +111,6 @@ void suspend_power_down(void) { #endif } -__attribute__((weak)) void matrix_power_up(void) {} -__attribute__((weak)) void matrix_power_down(void) {} -bool suspend_wakeup_condition(void) { - matrix_power_up(); - matrix_scan(); - matrix_power_down(); - for (uint8_t r = 0; r < MATRIX_ROWS; r++) { - if (matrix_get_row(r)) return true; - } - return false; -} - /** \brief run immediately after wakeup * * FIXME: needs doc @@ -137,16 +121,3 @@ void suspend_wakeup_init(void) { suspend_wakeup_init_quantum(); } - -#if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect) -/* watchdog timeout */ -ISR(WDT_vect) { - // compensate timer for sleep - switch (wdt_timeout) { - case WDTO_15MS: - timer_count += 15 + 2; // WDTO_15MS + 2(from observation) - break; - default:; - } -} -#endif |