Teensy 3.2 Reboot Hang when USB disconnected

I'm using _reboot_Teensyduino_() to restart the device after making configuration changes and saving changes to EEPROM. I noticed that during testing that I would encounter a hang if the USB port on the Teensy was not connected to anything. As soon as you plug the USB back in it completes the reboot cycle.

In this repro sample the unit will reboot after receiving 2 characters together on a TCP connection such as enter on telnet (using WIZ820io). If the USB is connected the reboot will be successful, otherwise it will not.

Code:
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <EEPROM.h>

#define LISTENTCP_PORT 10001


// Teensy 3.2

IPAddress staticIP(192,168,0,73);
IPAddress staticSubnet(255,255,254,0);




/** Retrieve Ethernet MAC from Teensy 3 */
class mac_addr : public Printable {
public:
    uint8_t m[6];

    mac_addr() {
        // Retrieve the 6 byte MAC address Paul burnt into two 32 bit words
        // at the end of the "READ ONCE" area of the flash controller.
        m[0] = m[1] = m[2] = m[3] = m[4] = m[5] = 0;
        read(0xe,0);
        read(0xf,3);
    }

    void read(uint8_t word, uint8_t loc) {

        // To understand what's going on here, see
        // "Kinetis Peripheral Module Quick Reference" page 85 and
        // "K20 Sub-Family Reference Manual" page 548.

        FTFL_FCCOB0 = 0x41;             // Selects the READONCE command
        FTFL_FCCOB1 = word;             // read the given word of read once area
                                        // -- this is one half of the mac addr.
        FTFL_FSTAT = FTFL_FSTAT_CCIF;   // Launch command sequence
        while(!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) {
                                        // Wait for command completion
        }
        *(m+loc) =   FTFL_FCCOB5;       // collect only the top three bytes,
        *(m+loc+1) = FTFL_FCCOB6;       // in the right orientation (big endian).
        *(m+loc+2) = FTFL_FCCOB7;       // Skip FTFL_FCCOB4 as it's always 0.
    }

    virtual size_t printTo(Print & p) const {
        size_t count = 0;
        for(uint8_t i = 0; i < 6; ++i) {
            if (i!=0) count += p.print(":");
            count += p.print((*(m+i) & 0xF0) >> 4, 16);
            count += p.print(*(m+i) & 0x0F, 16);
        }
        return count;
    }
};







EthernetServer server(LISTENTCP_PORT);


void StartNetwork()
{
  //Serial.print("Loading MAC from flash: ");
  //Serial.print("MAC: ");
  mac_addr mac;
  //Serial.println(mac);

  //Serial.println("Starting ethernet");

  Ethernet.begin(mac.m, staticIP, IPAddress(0,0,0,0), staticSubnet);

  server.begin();
}







// the setup routine runs once when you press reset:
void setup() 
{
  pinMode(19, OUTPUT);
  pinMode(20, OUTPUT);
  pinMode(21, OUTPUT);
  pinMode(22, OUTPUT);

  for (int i=0; i<10; i++)
  {
    digitalWrite(19, 1);
    digitalWrite(20, 1);
    digitalWrite(21, 1);
    digitalWrite(22, 1);
    delay(100);
    digitalWrite(19, 0);
    digitalWrite(20, 0);
    digitalWrite(21, 0);
    digitalWrite(22, 0);
    delay(100);
  }  

  StartNetwork();
}



int ReadCommandTCP(EthernetClient& client)
{
  //Serial.println("ReadCommandTCP() - Enter");
  int cb = 0;
  int w = 0;
  cb = client.connected();

  // just echo back for testing
  if (cb)
  {
    int navailable = client.available();
    if (navailable > 0)
    {
      while (navailable > 0 && client.connected())
      {
        byte buf[20];
        int maxread = navailable;
        if (maxread > 20)
          maxread = 20;
        int nRead = client.read(buf, maxread);
        if (nRead > 0)
        {
          navailable -= nRead;
          client.write(buf, nRead);
          w += nRead;
          if (nRead == 2)
          {
            client.print("Reboot ...");
            delay(500);
            _reboot_Teensyduino_();
          }
        }
        else
        {
          break;
        }
      }
    }
    else
    {
      // do other stuff
    }
  }
  return 0;
}


int t = 0;
EthernetClient client;
bool bClientConnected = false;



// the loop routine runs over and over again forever:
void loop() 
{
  if (bClientConnected)
  {
    if (client.connected())
    {
      ReadCommandTCP(client);
    }
    else
    {
      client.stop();
      bClientConnected = false;
    }
  }
  else
  {
    client = server.available();
    if (client)
    {
      bClientConnected = true;
    }
  }
}
 

Attachments

  • reboot_hang.ino
    3.8 KB · Views: 65
Of course it hangs, since it's going into bootloader mode where it waits for Teensy Loader to send new code.

If you want to reboot to your program, use SCB_AIRCR.
 
Ah, my bad. I assumed that it would follow the same path as a hardware power cycle.

Changed to SCB_AIRCR and that works.

Thanks!
 
Back
Top