update arduboy core

This commit is contained in:
Mr.Blinky 2019-07-22 22:24:23 +02:00 committed by GitHub
parent d15ba14a82
commit fedcf36ff2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 91 additions and 49 deletions

View File

@ -147,6 +147,18 @@ arduboy-homemade.menu.display.ssd1306.usb_product_postfix=1306
arduboy-homemade.menu.display.ssd1306.bootloader_display= arduboy-homemade.menu.display.ssd1306.bootloader_display=
arduboy-homemade.menu.display.ssd1306.build.extra_flags=-DARDUBOY_10 -DOLED_SSD1306 {build.flash_cs} {build.usb_flags} arduboy-homemade.menu.display.ssd1306.build.extra_flags=-DARDUBOY_10 -DOLED_SSD1306 {build.flash_cs} {build.usb_flags}
arduboy-homemade.menu.display.ssd1306i2c=SSD1306-I2C (2 Mbps)
arduboy-homemade.menu.display.ssd1306i2c.build.display=-ssd1306i2c
arduboy-homemade.menu.display.ssd1306i2c.usb_product_postfix=I2C
arduboy-homemade.menu.display.ssd1306i2c.bootloader_display=
arduboy-homemade.menu.display.ssd1306i2c.build.extra_flags=-DARDUBOY_10 -DOLED_SSD1306_I2C {build.flash_cs} {build.usb_flags}
arduboy-homemade.menu.display.ssd1306i2cx=SSD1306-I2C (2.66 Mbps)
arduboy-homemade.menu.display.ssd1306i2cx.build.display=-ssd1306i2cf
arduboy-homemade.menu.display.ssd1306i2cx.usb_product_postfix=I2CX
arduboy-homemade.menu.display.ssd1306i2cx.bootloader_display=
arduboy-homemade.menu.display.ssd1306i2cx.build.extra_flags=-DARDUBOY_10 -DOLED_SSD1306_I2CX {build.flash_cs} {build.usb_flags}
arduboy-homemade.menu.display.ssd1309=SSD1309 arduboy-homemade.menu.display.ssd1309=SSD1309
arduboy-homemade.menu.display.ssd1309.build.display=-ssd1309 arduboy-homemade.menu.display.ssd1309.build.display=-ssd1309
arduboy-homemade.menu.display.ssd1309.usb_product_postfix=1309 arduboy-homemade.menu.display.ssd1309.usb_product_postfix=1309

View File

@ -36,7 +36,7 @@ static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 };
static volatile int32_t breakValue = -1; static volatile int32_t breakValue = -1;
#ifndef ARDUBOY_CORE #ifndef ARDUBOY_CORE
bool _updatedLUFAbootloader = false; static u8 wdtcsr_save;
#else #else
extern volatile unsigned char bootloader_timer; extern volatile unsigned char bootloader_timer;
#endif #endif
@ -62,6 +62,11 @@ const CDCDescriptor _cdcInterface =
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0) D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0)
}; };
bool isLUFAbootloader()
{
return pgm_read_word(FLASHEND - 1) == NEW_LUFA_SIGNATURE;
}
int CDC_GetInterface(u8* interfaceNum) int CDC_GetInterface(u8* interfaceNum)
{ {
interfaceNum[0] += 2; // uses 2 interfaceNum[0] += 2; // uses 2
@ -97,10 +102,7 @@ bool CDC_Setup(USBSetup& setup)
if (CDC_SET_CONTROL_LINE_STATE == r) if (CDC_SET_CONTROL_LINE_STATE == r)
{ {
_usbLineInfo.lineState = setup.wValueL; _usbLineInfo.lineState = setup.wValueL;
}
if (CDC_SET_LINE_CODING == r || CDC_SET_CONTROL_LINE_STATE == r)
{
// auto-reset into the bootloader is triggered when the port, already // auto-reset into the bootloader is triggered when the port, already
// open at 1200 bps, is closed. this is the signal to start the watchdog // open at 1200 bps, is closed. this is the signal to start the watchdog
// with a relatively long period so it can finish housekeeping tasks // with a relatively long period so it can finish housekeeping tasks
@ -114,41 +116,43 @@ bool CDC_Setup(USBSetup& setup)
#if MAGIC_KEY_POS != (RAMEND-1) #if MAGIC_KEY_POS != (RAMEND-1)
// For future boards save the key in the inproblematic RAMEND // For future boards save the key in the inproblematic RAMEND
// Which is reserved for the main() return value (which will never return) // Which is reserved for the main() return value (which will never return)
if (_updatedLUFAbootloader) { if (isLUFAbootloader()) {
// horray, we got a new bootloader! // horray, we got a new bootloader!
magic_key_pos = (RAMEND-1); magic_key_pos = (RAMEND-1);
} }
#endif #endif
#endif #endif
// We check DTR state to determine if host port is open (bit 0 of lineState). // We check DTR state to determine if host port is open (bit 0 of lineState).
if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0) if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
{
#ifndef ARDUBOY_CORE #ifndef ARDUBOY_CORE
{
#if MAGIC_KEY_POS != (RAMEND-1) #if MAGIC_KEY_POS != (RAMEND-1)
// Backup ram value if its not a newer bootloader. // Backup ram value if its not a newer bootloader.
// This should avoid memory corruption at least a bit, not fully // This should avoid memory corruption at least a bit, not fully
if (magic_key_pos != (RAMEND-1)) { if (magic_key_pos != (RAMEND-1) && *(uint16_t *)magic_key_pos != MAGIC_KEY) {
*(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos; *(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos;
} }
#endif #endif
// Store boot key // Store boot key
*(uint16_t *)magic_key_pos = MAGIC_KEY; *(uint16_t *)magic_key_pos = MAGIC_KEY;
// Save the watchdog state in case the reset is aborted.
wdtcsr_save = WDTCSR;
wdt_enable(WDTO_120MS); wdt_enable(WDTO_120MS);
#else
bootloader_timer = 120; //ms
power_timer0_enable(); //power timer0 is disabled by flashlight/safemode in older Arduboy2 libraries
#endif
} }
else else if (*(uint16_t *)magic_key_pos == MAGIC_KEY)
{ {
#ifndef ARDUBOY_CORE
// Most OSs do some intermediate steps when configuring ports and DTR can // Most OSs do some intermediate steps when configuring ports and DTR can
// twiggle more than once before stabilizing. // twiggle more than once before stabilizing.
// To avoid spurious resets we set the watchdog to 250ms and eventually // To avoid spurious resets we set the watchdog to 120ms and eventually
// cancel if DTR goes back high. // cancel if DTR goes back high.
// Cancellation is only done if an auto-reset was started, which is
// indicated by the magic key having been set.
wdt_disable();
wdt_reset(); wdt_reset();
// Restore the watchdog state in case the sketch was using it.
WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = wdtcsr_save;
#if MAGIC_KEY_POS != (RAMEND-1) #if MAGIC_KEY_POS != (RAMEND-1)
// Restore backed up (old bootloader) magic key data // Restore backed up (old bootloader) magic key data
if (magic_key_pos != (RAMEND-1)) { if (magic_key_pos != (RAMEND-1)) {
@ -159,10 +163,17 @@ bool CDC_Setup(USBSetup& setup)
// Clean up RAMEND key // Clean up RAMEND key
*(uint16_t *)magic_key_pos = 0x0000; *(uint16_t *)magic_key_pos = 0x0000;
} }
#else
bootloader_timer = 0;
#endif
} }
#else
{
bootloader_timer = 120; //ms
power_timer0_enable(); //power timer0 is disabled by flashlight/safemode in older Arduboy2 libraries
}
else
{
bootloader_timer = 0;
}
#endif
} }
return true; return true;
} }

View File

@ -26,6 +26,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <inttypes.h> #include <inttypes.h>
#include <util/atomic.h>
#include "Arduino.h" #include "Arduino.h"
#include "HardwareSerial.h" #include "HardwareSerial.h"
@ -76,6 +77,13 @@ void serialEventRun(void)
#endif #endif
} }
// macro to guard critical sections when needed for large TX buffer sizes
#if (SERIAL_TX_BUFFER_SIZE>256)
#define TX_BUFFER_ATOMIC ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
#else
#define TX_BUFFER_ATOMIC
#endif
// Actual interrupt handlers ////////////////////////////////////////////////////////////// // Actual interrupt handlers //////////////////////////////////////////////////////////////
void HardwareSerial::_tx_udr_empty_irq(void) void HardwareSerial::_tx_udr_empty_irq(void)
@ -89,8 +97,14 @@ void HardwareSerial::_tx_udr_empty_irq(void)
// clear the TXC bit -- "can be cleared by writing a one to its bit // clear the TXC bit -- "can be cleared by writing a one to its bit
// location". This makes sure flush() won't return until the bytes // location". This makes sure flush() won't return until the bytes
// actually got written // actually got written. Other r/w bits are preserved, and zeroes
sbi(*_ucsra, TXC0); // written to the rest.
#ifdef MPCM0
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << MPCM0))) | (1 << TXC0);
#else
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << TXC0)));
#endif
if (_tx_buffer_head == _tx_buffer_tail) { if (_tx_buffer_head == _tx_buffer_tail) {
// Buffer empty, so disable interrupts // Buffer empty, so disable interrupts
@ -177,15 +191,13 @@ int HardwareSerial::read(void)
int HardwareSerial::availableForWrite(void) int HardwareSerial::availableForWrite(void)
{ {
#if (SERIAL_TX_BUFFER_SIZE>256) tx_buffer_index_t head;
uint8_t oldSREG = SREG; tx_buffer_index_t tail;
cli();
#endif TX_BUFFER_ATOMIC {
tx_buffer_index_t head = _tx_buffer_head; head = _tx_buffer_head;
tx_buffer_index_t tail = _tx_buffer_tail; tail = _tx_buffer_tail;
#if (SERIAL_TX_BUFFER_SIZE>256) }
SREG = oldSREG;
#endif
if (head >= tail) return SERIAL_TX_BUFFER_SIZE - 1 - head + tail; if (head >= tail) return SERIAL_TX_BUFFER_SIZE - 1 - head + tail;
return tail - head - 1; return tail - head - 1;
} }
@ -218,8 +230,22 @@ size_t HardwareSerial::write(uint8_t c)
// significantly improve the effective datarate at high (> // significantly improve the effective datarate at high (>
// 500kbit/s) bitrates, where interrupt overhead becomes a slowdown. // 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) { if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) {
*_udr = c; // If TXC is cleared before writing UDR and the previous byte
sbi(*_ucsra, TXC0); // completes before writing to UDR, TXC will be set but a byte
// is still being transmitted causing flush() to return too soon.
// So writing UDR must happen first.
// Writing UDR and clearing TC must be done atomically, otherwise
// interrupts might delay the TXC clear so the byte written to UDR
// is transmitted (setting TXC) before clearing TXC. Then TXC will
// be cleared when no bytes are left, causing flush() to hang
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
*_udr = c;
#ifdef MPCM0
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << MPCM0))) | (1 << TXC0);
#else
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << TXC0)));
#endif
}
return 1; return 1;
} }
tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE; tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE;
@ -240,9 +266,14 @@ size_t HardwareSerial::write(uint8_t c)
} }
_tx_buffer[_tx_buffer_head] = c; _tx_buffer[_tx_buffer_head] = c;
_tx_buffer_head = i;
// make atomic to prevent execution of ISR between setting the
sbi(*_ucsrb, UDRIE0); // head pointer and setting the interrupt flag resulting in buffer
// retransmission
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
_tx_buffer_head = i;
sbi(*_ucsrb, UDRIE0);
}
return 1; return 1;
} }

View File

@ -35,9 +35,6 @@ extern const u16 STRING_LANGUAGE[] PROGMEM;
extern const u8 STRING_PRODUCT[] PROGMEM; extern const u8 STRING_PRODUCT[] PROGMEM;
extern const u8 STRING_MANUFACTURER[] PROGMEM; extern const u8 STRING_MANUFACTURER[] PROGMEM;
extern const DeviceDescriptor USB_DeviceDescriptorIAD PROGMEM; extern const DeviceDescriptor USB_DeviceDescriptorIAD PROGMEM;
#ifndef ARDUBOY_CORE
extern bool _updatedLUFAbootloader;
#endif
const u16 STRING_LANGUAGE[2] = { const u16 STRING_LANGUAGE[2] = {
(3<<8) | (2+2), (3<<8) | (2+2),
@ -821,14 +818,6 @@ void USBDevice_::attach()
UDIEN = (1<<EORSTE) | (1<<SOFE) | (1<<SUSPE); // Enable interrupts for EOR (End of Reset), SOF (start of frame) and SUSPEND UDIEN = (1<<EORSTE) | (1<<SOFE) | (1<<SUSPE); // Enable interrupts for EOR (End of Reset), SOF (start of frame) and SUSPEND
TX_RX_LED_INIT; TX_RX_LED_INIT;
#ifndef ARDUBOY_CORE
#if MAGIC_KEY_POS != (RAMEND-1)
if (pgm_read_word(FLASHEND - 1) == NEW_LUFA_SIGNATURE) {
_updatedLUFAbootloader = true;
}
#endif
#endif
} }
void USBDevice_::detach() void USBDevice_::detach()

View File

@ -285,8 +285,7 @@ typedef struct
// Old Caterina bootloader places the MAGIC key into unsafe RAM locations (it can be rewritten // Old Caterina bootloader places the MAGIC key into unsafe RAM locations (it can be rewritten
// by the running sketch before to actual reboot). // by the running sketch before to actual reboot).
// Newer bootloaders, recognizable by the LUFA "signature" at the end of the flash, can handle both // Newer bootloaders, recognizable by the LUFA "signature" at the end of the flash, can handle both
// the usafe and the safe location. Check once (in USBCore.cpp) if the bootloader in new, then set the global // the usafe and the safe location.
// _updatedLUFAbootloader variable to true/false and place the magic key consequently
#ifndef MAGIC_KEY #ifndef MAGIC_KEY
#define MAGIC_KEY 0x7777 #define MAGIC_KEY 0x7777
#endif #endif

View File

@ -46,8 +46,8 @@ volatile unsigned char button_ticks_now = 0;
volatile unsigned char button_ticks_last = 0; volatile unsigned char button_ticks_last = 0;
volatile unsigned char bootloader_timer = 0; volatile unsigned char bootloader_timer = 0;
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) #if defined(TIM0_OVF_vect)
ISR(TIM0_OVF_vect) ISR(TIM0_OVF_vect)
#else #else
ISR(TIMER0_OVF_vect, ISR_NAKED) ISR(TIMER0_OVF_vect, ISR_NAKED)
#endif #endif