Fix flashlight() and safeMode() for boot problem

- Timer 0 is disabled in flashlight() and safeMode() in case its
  variables overlap the bootloader "magic key" location.
- Flashlight mode never exits if invoked.
- Made safeMode() public for use as a smaller code size alternative
  to flashlight().
This commit is contained in:
Scott Allen 2017-03-24 15:53:35 -04:00
parent a85c6da431
commit a8077a756e
5 changed files with 57 additions and 34 deletions

View File

@ -67,6 +67,7 @@ pollButtons KEYWORD2
pressed KEYWORD2
readUnitID KEYWORD2
readUnitName KEYWORD2
safeMode KEYWORD2
saveOnOff KEYWORD2
setCursor KEYWORD2
setFrameRate KEYWORD2

View File

@ -54,22 +54,25 @@ void Arduboy2Base::begin()
void Arduboy2Base::flashlight()
{
if(!pressed(UP_BUTTON)) {
if (!pressed(UP_BUTTON)) {
return;
}
sendLCDCommand(OLED_ALL_PIXELS_ON); // smaller than allPixelsOn()
digitalWriteRGB(RGB_ON, RGB_ON, RGB_ON);
while (!pressed(DOWN_BUTTON)) {
// prevent the bootloader magic number from being overwritten by timer 0
// when a timer variable overlaps the magic number location, for when
// flashlight mode is used for upload problem recovery
power_timer0_disable();
while (true) {
idle();
}
digitalWriteRGB(RGB_OFF, RGB_OFF, RGB_OFF);
sendLCDCommand(OLED_PIXELS_FROM_RAM);
}
void Arduboy2Base::systemButtons() {
void Arduboy2Base::systemButtons()
{
while (pressed(B_BUTTON)) {
digitalWriteRGB(BLUE_LED, RGB_ON); // turn on blue LED
sysCtrlSound(UP_BUTTON + B_BUTTON, GREEN_LED, 0xff);
@ -80,7 +83,8 @@ void Arduboy2Base::systemButtons() {
digitalWriteRGB(BLUE_LED, RGB_OFF); // turn off blue LED
}
void Arduboy2Base::sysCtrlSound(uint8_t buttons, uint8_t led, uint8_t eeVal) {
void Arduboy2Base::sysCtrlSound(uint8_t buttons, uint8_t led, uint8_t eeVal)
{
if (pressed(buttons)) {
digitalWriteRGB(BLUE_LED, RGB_OFF); // turn off blue LED
delay(200);

View File

@ -195,16 +195,30 @@ class Arduboy2Base : public Arduboy2Core
void begin();
/** \brief
* Flashlight mode turns the RGB LED and display fully on.
* Turn the RGB LED and display fully on to act as a small flashlight/torch.
*
* \details
* Checks if the UP button is pressed and if so turns the RGB LED and all
* display pixels fully on. Pressing the DOWN button will exit flashlight mode.
* display pixels fully on. If the UP button is detected, this function
* does not exit. The Arduboy must be restarted after flashlight mode is used.
*
* This function is called by `begin()` and can be called by a sketch
* after `boot()`.
*
* \see begin() boot()
* \note
* \parblock
* This function also contains code to address a problem with uploading a new
* sketch, for sketches that interfere with the bootloader "magic number".
* This problem occurs with certain sketches that use large amounts of RAM.
* Being in flashlight mode when uploading a new sketch can fix this problem.
*
* Therefore, for sketches that potentially could cause this problem, and use
* `boot()` instead of `begin()`, it is recommended that a call to
* `flashlight()` be included after calling `boot()`. If program space is
* limited, `safeMode()` can be used instead of `flashlight()`.
* \endparblock
*
* \see begin() boot() safeMode()
*/
void flashlight();

View File

@ -82,12 +82,6 @@ void Arduboy2Core::boot()
bootPins();
bootOLED();
#ifdef SAFE_MODE
if (buttonsState() == (LEFT_BUTTON | UP_BUTTON))
safeMode();
#endif
bootPowerSaving();
}
@ -240,9 +234,15 @@ void Arduboy2Core::SPItransfer(uint8_t data)
void Arduboy2Core::safeMode()
{
blank(); // too avoid random gibberish
while (true) {
asm volatile("nop \n");
if (buttonsState() == UP_BUTTON)
{
digitalWriteRGB(RED_LED, RGB_ON);
// prevent the bootloader magic number from being overwritten by timer 0
// when a timer variable overlaps the magic number location
power_timer0_disable();
while (true) { }
}
}

View File

@ -32,11 +32,6 @@
// #define AB_DEVKIT //< compile for the official dev kit
#endif
#ifdef AB_DEVKIT
#define SAFE_MODE //< include safe mode (44 bytes)
#endif
#define RGB_ON LOW /**< For digitially setting an RGB LED on using digitalWriteRGB() */
#define RGB_OFF HIGH /**< For digitially setting an RGB LED off using digitalWriteRGB() */
@ -619,19 +614,28 @@ class Arduboy2Core
*/
void static boot();
protected:
/*
* Safe Mode is engaged by holding down both the LEFT button and UP button
* when plugging the device into USB. It puts your device into a tight
* loop and allows it to be reprogrammed even if you have uploaded a very
* broken sketch that interferes with the normal USB triggered auto-reboot
* functionality of the device.
/** \brief
* Allow upload when the bootloader "magic number" could be corrupted.
*
* This is most useful on Devkits because they lack a built-in reset
* button.
* \details
* If the UP button is held when this function is entered, the RGB LED
* will be lit and timer 0 will be disabled, then the sketch will remain
* in a tight loop. This is to address a problem with uploading a new
* sketch, for sketches that interfere with the bootloader "magic number".
* The problem occurs with certain sketches that use large amounts of RAM.
*
* This function should be called after `boot()` in sketches that
* potentially could cause the problem.
*
* It is intended to replace the `flashlight()` function when more
* program space is required. If possible, it is more desirable to use
* `flashlight()`, so that the actual flashlight feature isn't lost.
*
* \see Arduboy2Base::flashlight() boot()
*/
void static inline safeMode() __attribute__((always_inline));
void static safeMode();
protected:
// internals
void static inline setCPUSpeed8MHz() __attribute__((always_inline));
void static inline bootOLED() __attribute__((always_inline));