Add better bootloader-workaround for atmega32u4 based Arduinos
This commit is contained in:
parent
b90d445ce3
commit
7cc1248abf
82
flame.ino
82
flame.ino
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Flaming Torch (c) 2013-2014 Simon Budig <simon@budig.de>
|
* Flaming Torch (c) 2013-2019 Simon Budig <simon@budig.de>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#define PIN_BUTTON 3 // Input pin für Button
|
#define PIN_BUTTON 3 // Input pin für Button
|
||||||
#define PIN_LED 2 // Output pin für Led-Strip
|
#define PIN_LED 2 // Output pin für Led-Strip
|
||||||
#define NUM_PIXELS (1 * 30)
|
#define NUM_PIXELS (5 * 64)
|
||||||
|
|
||||||
#define NUM_MODES 6
|
#define NUM_MODES 6
|
||||||
|
|
||||||
@ -271,8 +271,6 @@ setup ()
|
|||||||
|
|
||||||
|
|
||||||
// Arduino Loop function. Repeats continuously
|
// Arduino Loop function. Repeats continuously
|
||||||
// (for Leonardo there is some USB-Handling implicitely inbetween,
|
|
||||||
// for some reason the bootloader isn't entered properly.
|
|
||||||
|
|
||||||
void
|
void
|
||||||
loop ()
|
loop ()
|
||||||
@ -281,12 +279,64 @@ loop ()
|
|||||||
static uint16_t t = 0xffff;
|
static uint16_t t = 0xffff;
|
||||||
static uint8_t pressed = 0;
|
static uint8_t pressed = 0;
|
||||||
static uint8_t state = 0xff;
|
static uint8_t state = 0xff;
|
||||||
|
uint8_t delay_value = 0;
|
||||||
|
|
||||||
|
#ifdef MAGIC_KEY_POS
|
||||||
|
// for atmega32u4 based Arduinos:
|
||||||
|
//
|
||||||
|
// check if the bootloader has been activated.
|
||||||
|
// avoid doing any rendering to prevent the
|
||||||
|
// MAGIC_KEY getting overridden which in turn
|
||||||
|
// would prevent entering the bootloader properly.
|
||||||
|
|
||||||
|
if (*((uint16_t *) MAGIC_KEY_POS) == MAGIC_KEY &&
|
||||||
|
WDTCSR & (1 << WDE))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (state >= NUM_MODES)
|
if (state >= NUM_MODES)
|
||||||
state = EEPROM.read(0);
|
state = EEPROM.read(0);
|
||||||
if (state >= NUM_MODES)
|
if (state >= NUM_MODES)
|
||||||
state = 0;
|
state = 0;
|
||||||
|
|
||||||
|
#ifdef MAGIC_KEY_POS
|
||||||
|
// Now, this is quite unfortunate:
|
||||||
|
//
|
||||||
|
// for the atmege32u4 based arduinos (Leonardo, pro micro etc.)
|
||||||
|
// entering the bootloader is initiated in the USB interrupt
|
||||||
|
// handler (i.e. can happen at any time).
|
||||||
|
//
|
||||||
|
// This does two things: writes MAGIC_KEY to MAGIC_KEY_POS and
|
||||||
|
// enables the watchdog reset.
|
||||||
|
//
|
||||||
|
// If the watchdog fires the atmega32u4 resets and the bootloader
|
||||||
|
// code checks for the MAGIC_KEY at MAGIC_KEY_POS. If it finds
|
||||||
|
// the MAGIC_KEY it sticks in the bootloader mode.
|
||||||
|
//
|
||||||
|
// for larger LED strips it is quite likely that MAGIC_KEY_POS
|
||||||
|
// resides in the middle of the framebuffer. And if the USB interrupt
|
||||||
|
// happens while the code is rendering stuff to the framebuffer,
|
||||||
|
// it then might happen that the MAGIC_KEY immediately gets overwritten
|
||||||
|
// by the rendering code. This prevents that the bootloader gets
|
||||||
|
// entered upon the watchdog reset. For some effects the AVR is mostly
|
||||||
|
// rendering, making it basically impossible to enter the bootloader
|
||||||
|
// via the IDE.
|
||||||
|
//
|
||||||
|
// As a workaround we disable all interrupts during the rendering code
|
||||||
|
// which is quite a brute force method. This delays the writing of the
|
||||||
|
// MAGIC_KEY to the point of the sei() (since this is now the point where
|
||||||
|
// the USB interrupt gets handled), giving the MAGIC_KEY precedence over
|
||||||
|
// the rendered effect.
|
||||||
|
//
|
||||||
|
// and since we basically avoid running loop() when the
|
||||||
|
// bootloader-conditions are met (see above) the switch to the bootloader
|
||||||
|
// now is more reliable again.
|
||||||
|
|
||||||
|
cli ();
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
@ -295,27 +345,27 @@ loop ()
|
|||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
render_blueyellow (t);
|
render_blueyellow (t);
|
||||||
delay (10);
|
delay_value = 10;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
render_rainbow (t);
|
render_rainbow (t);
|
||||||
delay (10);
|
delay_value = 10;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
render_redblue (t);
|
render_redblue (t);
|
||||||
delay (10);
|
delay_value = 10;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
render_kitt (t);
|
render_kitt (t);
|
||||||
delay (20);
|
delay_value = 20;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
render_rgbsparks (t);
|
render_rgbsparks (t);
|
||||||
delay (10);
|
delay_value = 10;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -323,6 +373,18 @@ loop ()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAGIC_KEY_POS
|
||||||
|
sei ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// the actual delay relies on interupts, hence
|
||||||
|
// we have to do the per-frame-waiting after the sei();
|
||||||
|
|
||||||
|
if (delay_value)
|
||||||
|
{
|
||||||
|
delay (delay_value);
|
||||||
|
}
|
||||||
|
|
||||||
// Time-Tick. Needed for moving stripes
|
// Time-Tick. Needed for moving stripes
|
||||||
t--;
|
t--;
|
||||||
|
|
||||||
@ -354,5 +416,3 @@ loop ()
|
|||||||
pressed = 5;
|
pressed = 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user