_reboot_Teensyduino() vs. _restart_Teensyduino()

Status
Not open for further replies.

kam42

Active member
Hello all!

Question based on previous question located here: http://forum.pjrc.com/threads/23776-Teensy2-0-Software-Reset

Does the _restart_Teensyduino_() method exist for the Teensy3? I see it located in core_pins.h, but I get an error when trying to compile an example sketch with it. _reboot_Teensyduino() works fine, but requires the Teensyduino software to be open, and results in a reprogram command.

My usage case is for a controlled soft-reboot, without re-uploading the program. I have an integrated battery and charger, and don't expect the Teensy to ever be rebooted due to loss of power or a reprogram event, so would like to hedge against long-timeline problems developing that are generally hard to foresee and test..

Any help would be appreciated, thanks for your help in advance.
 
Apologies, example code:

Don't leave it running, it results in a reprogram loop every 5 seconds.

Replacing _reboot_Teensyduino_(); with _restart_Teensyduino_() results in an error.

void setup(){

// Note, nonstandard Teensy 3 output LED pin.
pinMode(5, OUTPUT);
digitalWrite(5, HIGH);
delay(50);
digitalWrite(5, LOW);


delay(5000);

_reboot_Teensyduino_();



}

void loop(){
digitalWrite(5, !digitalRead(5));
delay(200);


}
 
I love the watchdog timer chip - that would be more robust than a purely programmatic reboot request.

I saw in the MK20 documentation that it has an internal watchdog timer, I will have to look into that as well. Thanks for the idea!


In the meantime though, I'd like to get the restart function working - I must be missing something, because the reboot function works exactly as advertised.
 
Does the _restart_Teensyduino_() method exist for the Teensy3?

No, this has not yet been implemented for Teensy 3.0.

If you just want to reboot the chip, I believe software reset using a hardware register should be possible. From the reference manual:

6.2.2.8 Software reset (SW)
The SYSRESETREQ bit in the NVIC application interrupt and reset control register can
be set to force a software reset on the device. (See ARM's NVIC documentation for the
full description of the register fields, especially the VECTKEY field requirements.)
Setting SYSRESETREQ generates a software reset request. This reset forces a system
reset of all major components except for the debug module. A software reset causes the
RCM's SRS1[SW] bit to set.

Here's the ARM documentation:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/Cihcbadd.html

Scroll down to the "Application Interrupt and Reset Control Register" section (I can't find a way to copy a link directly to that part). You can also click the left side to expand "NVIC register descriptions" and click it from the list.

So in theory, writing the correct value to address 0xE000ED0C ought to cause a software reset.


However, a software reset might reset the USB, which can cause a USB disconnect. The _restart_Teensyduino_() tries to simulate a reboot, but without the USB disconnecting. It is quite difficult to implement, because this requires the USB stack to be able to detect previous initialization. Teensy 2.0's USB stack was rewritten a couple years ago for this purpose. So far, I haven't done this with Teensy3. It's quite a lot of work!


If you do explore using the ARM AIRCR register, please post here about what worked (or didn't work).
 
Paul,

Thanks for the reply, I'll look into the documentation you kindly provided and report back. Fortunately, I would be calling the software reset after the USB is disconnected so I don't think that will be a major issue.
 
Did you know there are two programmable processors on the Teensy 3? Well, one of them is only programmable by Paul, but it's still programmable. So another long term approach would be to sweet talk Paul into implementing a watchdog in the Cortex-M0 processor that boots the main Cortex-M4. ;)

Am I correct in assuming this is thread is for learning about fault-tolerance, not using a hobby board for functional safety where there is a significant hazard to people or property? If safety is an issue, a broader conversation might be prudent.
 
Good point about the M0, that would be fantastic.

Correct with respect to fault tolerance - these boards aren't going into anything related to functional safety. Pure data acquisition and logging boards. My concern is that running these continuously for 6 months is a difficult usage case to debug, and I like the idea of having a relatively fresh start every so often. Hence, a reset after completing data download and battery charge.
 
So another long term approach would be to sweet talk Paul into implementing a watchdog in the Cortex-M0 processor that boots the main Cortex-M4. ;)

I'm open to feedback and ideas, but first I need to understand why a feature would be valuable and have a good idea of how it should actually work. So far regarding this reboot, neither of those are clear to me. Then any new feature needs to have some significant advantage over other ways, in this case using the watchdog that's already built into the chip. Then, of course, it goes onto my extremely long to-do list. But like many other things, such as the low power update, I do usually get to them eventually. But especially with change in the Mini54 chip, my strong preference is "ain't broke, don't fix", so first I'd really like to talk about the MK20's watchdog timer and other capabilities.
 
Hi Paul,

I had some time to work with your above points, and have successfully rebooted both my custom boards and normal Teensy 3.0 boards using the below code. Required writing to the SYSRESETREQ bit. The program is rough, and doesn't follow the normal register conventions of offsets and shifts as I am not very familiar with them.

Code:
// Should restart Teensy 3, will also disconnect USB during restart

// From http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/Cihcbadd.html
// Search for "0xE000ED0C"
// Original question http://forum.pjrc.com/threads/24304-_reboot_Teensyduino%28%29-vs-_restart_Teensyduino%28%29?p=35981#post35981

#define RESTART_ADDR       0xE000ED0C
#define READ_RESTART()     (*(volatile uint32_t *)RESTART_ADDR)
#define WRITE_RESTART(val) ((*(volatile uint32_t *)RESTART_ADDR) = (val))

void setup(){

  // startup routine
  pinMode(13, OUTPUT);

  digitalWrite(13, HIGH);
  for(int i = 0; i < 10; i++){
    digitalWrite(13, !digitalRead(13));
    delay(200);
  }  

  delay(1000);

  // 0000101111110100000000000000100
  // Assert [2]SYSRESETREQ
  WRITE_RESTART(0x5FA0004);
}

 // Should never get here. 
void loop(){}

Let me know if this works for you also.
 
How are the data downloaded? If there's a network, then there's a possibility of putting a watchdog on the net. This could have the added advantage of having a separate power source and the ability to report failures.

By the way, is it legal to call digitalRead() on an output and what does it do?
 
By the way, is it legal to call digitalRead() on an output and what does it do?

Nifty little trick I learned here on the forum to easily blink a light. From my experience with it, seems it is possible to call digitalRead on an output.

Data downloaded via software serial over USB from the microSD card to a host computer.

I currently have the restart set to run every time it detects the USB cable disconnected from the device.
 
HI there,
Thanks for posting the code on how to reset the Teensy 3. I could sure use it.
It doesn't seem like the whole code posted to the thread? I only see the setup() call but not the loop or the definition of WRITE_RESTART.
Thanks for any follow up...
In my case, I'm specifically trying to reset the Teensy if the USB connection gets ;lost'. For some reason, my Teensy sometimes does this, probably because it contains I2C code to a sensor, and that itself gets hosed because the I2C code can get hung permanently.
 
It's all there, the loop is empty since code should never get there. The definition of WRITE_RESTART is defined before setup(), #define WRITE_RESTART(val) ((*(volatile uint32_t *)RESTART_ADDR) = (val))
 
because it contains I2C code to a sensor, and that itself gets hosed because the I2C code can get hung permanently.

It's not a good idea to fix that problem with a watchdog timer. There is an alternative i2C library available that has a timeout/restart function that would help overcome the problem temporarily but ultimately its better to find and fix the root cause. It could well be a problem with noise/signal integrity on the I2C bus.
 
It's not a good idea to fix that problem with a watchdog timer. There is an alternative i2C library available that has a timeout/restart function that would help overcome the problem temporarily but ultimately its better to find and fix the root cause. It could well be a problem with noise/signal integrity on the I2C bus.

Thanks, and yes I believe you could be right about the lines.
What is the name of that I2C library with the timeout? That would be a great start.
 
It's all there, the loop is empty since code should never get there. The definition of WRITE_RESTART is defined before setup(), #define WRITE_RESTART(val) ((*(volatile uint32_t *)RESTART_ADDR) = (val))

Thanks. For some reason the void loop() doesn't show on my screen, and the code stopped at '...get here.' I added the void loop(){} and it works. Thanks for that, I can definitely use it...
 
It's not a good idea to fix that problem with a watchdog timer. There is an alternative i2C library available that has a timeout/restart function that would help overcome the problem temporarily but ultimately its better to find and fix the root cause. It could well be a problem with noise/signal integrity on the I2C bus.

THIS is the alternative I2C library written by user nox771. I have not used the timeout feature with that particular library, but if you have questions about its application please ask in the thread I linked to.
 
THIS is the alternative I2C library written by user nox771. I have not used the timeout feature with that particular library, but if you have questions about its application please ask in the thread I linked to.

Thanks. I have been using this library for a while, and had tried a while back to get the timeout feature to fix my issue, and hadn't got it to work. But now with that code plus the WRITE_RESTART, I've got a fix. Super. Mind you , as you point out, the root I2C miscomm is still undiagnosed, but I don't actually have time to get to it...
 
Thanks for the posts, the WRITE_RESTART(0x5FA0004) worked for me.
As its a visible debug element, and I generate a system status report when the user inputs '?'
I generate the following

Code:
resetReason();
and gives a console output

ResetReason:0x40 ExtResetPin - on reprogramming
ResetReason:0x400 SoftWare - on executing a WRITE_RESTART(0x5FA0004)

which has the following components

Code:
   //K20 - on startup
  resetReasonHw= RCM_SRS0;
  resetReasonHw |= (RCM_SRS1<<8);

Code:
void resetReason() {
	uint16_t mask=1;
	Serial.print(strReason);
	Serial.print(resetReasonHw,HEX);
	do {
		switch (mask & resetReasonHw){
		//RCM_SRS0
		case 0x0001: Serial.print(F(" wakeup")); break;
		case 0x0002: Serial.print(F(" LowVoltage"));  break;
		case 0x0004: Serial.print(F(" LossOfClock")); break;
		case 0x0008: Serial.print(F(" LossOfLock")); break;
		//case 0x0010 reserved
		case 0x0020: Serial.print(F(" wdog")); break;
		case 0x0040: Serial.print(F(" ExtResetPin")); break;
		case 0x0080: Serial.print(F(" PwrOn")); break;

		//RCM_SRS1
		case 0x0100: Serial.print(F(" JTAG")); break;
		case 0x0200: Serial.print(F(" CoreLockup")); break;
		case 0x0400: Serial.print(F(" SoftWare")); break;
		case 0x0800: Serial.print(F(" MDM_AP")); break;

		case 0x1000: Serial.print(F(" EZPT")); break;
		case 0x2000: Serial.print(F(" SACKERR")); break;
		//default:  break;
		}
	} while (mask <<= 1);
}
 
Last edited:
Work-around for lack of restart in libraries for Teensy 3, and adapting from the above by kam32, here's a concise way to restart a Teensy 3 (not reboot which tries to down
Code:
#define CPU_RESTART_ADDR (uint32_t *)0xE000ED0C
#define CPU_RESTART_VAL 0x5FA0004
#define CPU_RESTART (*CPU_RESTART_ADDR = CPU_RESTART_VAL);

then just use the macro CPU_RESTART in your application.
 
Hi stevech

I want to reset the teensy because it should become in the initial state.
I have tried the CPU_RESTART macro and the _reboot_Teensyduino() procedure but did not work for me.
I have tried this with when I was connected to the hardware serial port (USB) and via the AltSoftSerial ports.
When I used the _reboot_Tensyduino(), then the Teensy tries to load the software again, and if not present it hangs.
When I tried the CPU_RESART it sometimes hangs and somtimes not. Unpredictable;
What can I do more to have a gracefull restart?

EDIT: Found it. I still had other hard reboot code in the project
 
Last edited:
Hiya. Arduino noob here First post on forums.

I guess I am posting this for other noobs out there looking to implement a soft reboot into the code- ie: reprogramming mode

Copying from stevech above:

#define CPU_REBOOT (_reboot_Teensyduino_());

Then use CPU_REBOOT; in your loop.


//*****Example Code:********

Code:
/*
  
  ON REBOOT:   -Flashes LEDS five times quickly on reboot.
 
  IN THE LOOP: -In the loop Flashes led once quickly, once not so quickly
                       -2 second pause and puts the Teensy 3.1 into Reboot Mode

  NOTE: If Teensy application is set to auto, it will reload current hex file
 */
 
// Pin 13 has an LED connected on the Arduino 3.1 board.


#define CPU_REBOOT (_reboot_Teensyduino_());
int led = 13;

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
    pinMode(led, OUTPUT);     
    digitalWrite(13, HIGH);
    for(int i = 0; i < 10; i++){
    digitalWrite(13, !digitalRead(13));
    delay(50);
  }
  digitalWrite(led, LOW);
  delay(500);
  

}

void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(100);               // wait for the blink of an eye
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(100);               // wait for a second
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(2000);               // wait for two seconds before reboot
 // CPU_REBOOT ;
 CPU_REBOOT ;

}
 
Last edited:
Nifty little trick I learned here on the forum to easily blink a light. From my experience with it, seems it is possible to call digitalRead on an output.

Data downloaded via software serial over USB from the microSD card to a host computer.

I currently have the restart set to run every time it detects the USB cable disconnected from the device.


while you can use !digitalRead to blink LED, another option is to use the bitband toggle macro like this

Code:
*portToggleRegister(LEDPIN) = 1;
 
Status
Not open for further replies.
Back
Top