Bugs in custom audio library objects make Teensy unflashable

Status
Not open for further replies.
I've been working on some new effect objects using the Teensy Audio Library and have run into an annoying problem. Sometimes, if I've made a mistake in my code somewhere, it causes the Teensy to become completely unflashable.

Here's a firmware to illustrate my point:

Code:
#include <Audio.h> // Teensy audio library
#include "AudioStream.h"
const bool DEBUG = true; // Debugging over serial

class AudioEffectCrashTeensy : public AudioStream
{
public:
  AudioEffectCrashTeensy() : AudioStream(0, NULL) {}
  
  virtual void update(void) {
      audio_block_t *block;

      block = receiveReadOnly();
      if (!block) return;

      transmit(block);
      release(block);
    }
private:
  audio_block_t *inputQueueArray[1];
};

// Initialise audio objects
AudioSynthWaveform  waveform1;
AudioEffectCrashTeensy effect1;
AudioOutputI2S  i2s1;
AudioConnection patchCord4(waveform1, effect1);
AudioConnection patchCord2(effect1, 0, i2s1, 0);
AudioConnection patchCord3(effect1, 0, i2s1, 1);

void setup() {
  if (DEBUG){
    Serial.begin(9600);
    while (!Serial);
    Serial.println("Debug enabled. If overwriting bad firmware, do it now.\n10 seconds until main loop begins...");
    delay(1000);
    for (int i=9; i>0; i--){
      Serial.println(i);
      delay(1000);
    }
    Serial.println("Audio on.");
  }

  AudioMemory(10);
  waveform1.frequency(440);
  waveform1.amplitude(1.0);
  waveform1.begin(WAVEFORM_TRIANGLE);
}

void loop() {
  AudioNoInterrupts();
  AudioInterrupts();
}

This contains a mistake: the constructor should be
Code:
AudioStream(1, inputQueueArray)
The result is if this code is allowed to enter the main loop() function, it completely freezes up the Teensy to the point where it no longer accepts commands over serial and cannot be flashed. The only way to fix it is to do a factory reset by holding down the button for 15 seconds. This is an un-workable solution for me as my teensies are hidden inside a case with a fair bit of disassembly required to get to the button.

Merely trying not to make any mistakes in my code is also not a workable solution. Mistakes are a normal part of development! What I really need is a way to be able to test my code without fear of accidentally placing the Teensy in an unflashable state.

As a work-around, I've placed a 10 second delay in the setup() function, which gives me time to flash the Teensy after resetting power in the case that I make a mistake in my audio library development. However, that's not ideal either.

Any suggestions? Is this a bug in the audio core? Could it be made more resilient?

The other thing I'm wondering is what affect (if any) AudioNoInterrupts() vs AudioInterrupts() would have on this problem.
 
Teensy in use not indicated? Assuming a 4.x but 3.5 and 3.6 also have the factory Restore

It should come back to programmable with just a Button press {perhaps a power Off/On} - not needing Restore ... unless it is somehow trashing something deep that the restore fixes.

Yes, that still requires the button ... If this is just a development issue just wire out the Program Pin to a button.

Though it could somehow be using the OFF function which is stored until given a hardware ON Signal, or all power fades - including vBat if connected?

Ideally it is Faulting with a NULL pointer reference or something ... and if the fault was trapped generally it can stop there in a loop and USB can still function to allow Auto programming.

CORES has code that can lead to showing something - but that is diff between 4.x and 3.x ...
 
Teensy in use not indicated?
It's a 4.1 :)

It should come back to programmable with just a Button press {perhaps a power Off/On} - not needing Restore ... unless it is somehow trashing something deep that the restore fixes.
Yes, that still requires the button ...

Bang on! The button is completely inaccessible for my application, and the device also needs to be user programmable. So either way, I need a reliable way to prevent the USB from locking up.

or all power fades - including vBat if connected?

Resetting power doesn't help unfortunately.

Ideally it is Faulting with a NULL pointer reference or something ... and if the fault was trapped generally it can stop there in a loop and USB can still function to allow Auto programming.

This sounds like it might be helpful... could you explain further?

Thanks.
J
 
> a 10 second delay in the setup() function, which gives me time to flash the Teensy ... not ideal

Maybe you could write some code that only does this delay if the previous run of the program was unsuccessful. For example (pseudo code):

Code:
setup() {
   if (eeprom_delay == 1) 
      delay(10000)   or more

   eeprom_delay = 1;
}

loop() {
   if (eeprom_delay == 1 && program running properly for > 10 seconds) 
      eeprom_delay = 0
}
 
As someone else mentioned, the program button is also available on header pins on the T4.1. I would highly recommend bringing this signal out to an enclosure mounted button. A small tactile switch like the kind use to reset your router with a paperclip is common on devices that should not be opened.

However, you can also help mitigate the problem by using the watchdog. Look for WDT_T4 library. If something crashes, at least the board will auto-reboot. If whatever is causing the crash happens immediately after reboot, you are back to having to press the enclosure mounted button.

I would not recommend putting yourself in a situation where a crash results in having to open the enclosure because you didn't bring out the program button.
 
The latest betas have a fault handler which tries to keep USB responsive after a memory fault and automatically reboots after 8 seconds.

If anyone following this thread wants to give it a try, here's is the most recent.

https://forum.pjrc.com/threads/67612-Teensyduino-1-54-Beta-12

No software can cover 100% of all cases where things go wrong (the reason a physical button exists on every Teensy), but hopefully this new software improves many of them.
 
This is great Paul, thank you!
And in response to Blackaddr, you are definitely right. Having user access to the program button is a very good idea.
 
Status
Not open for further replies.
Back
Top