Teensy 3.2 startup_early_hook appears to hang?

Status
Not open for further replies.

r5gordini

Member
Hi All,

I've designed and built my own custom Teensy 3.2 and all appears to be working fine with it - been running many different sketches on it over the last few weeks.

However, I now have a problem. My power supply chip, an Infineon TLE73683EXUMA2 has a hardware watchdog that I'd like to take advantage of. I finally managed to enable the watchdog, but it has very specific timing requirements. It seems that I need to give it a "kick" within about 50ms of the processor being reset.

So - after much searching and trial and error I found the information about startup_early_hook, which sounded like just what I needed! The delays around bringing the USB up are about 400ms, which is too long for me to be able to kick the watchdog. Therefore, if the processor crashes, I just get endless resets triggered by the watchdog.

The challenge is that I can't get any of the sample code I have found for using startup_early_hook to work! It seems that the processor just hangs.

Even this test sketch, with no code at all within the startup_early_hook, causes the hang, and the LED (attached to Pin 7 on my board) does not illuminate:

Code:
#ifdef __cplusplus
extern "C" {
#endif
void startup_early_hook() {

}
#ifdef __cplusplus
}
#endif


void setup() {
  pinMode(7, OUTPUT);
  digitalWrite(7, HIGH);
  Serial.begin(115200);
  delay(2000);

}

void loop() {
  delay(100);
  Serial.println("hi");
}

Does anyone have any thoughts or suggestions? I'm using Teensyduino 1.53. Would really love to be able to get this to work ;-)

Also - another rather major issue I've just thought of - if we've got a 400ms delay during bringing the USB up, how might I kick the watchdog every 50ms during that delay? Interrupts/timers? And no - there's no way to disable the watchdog on the power supply chip once it's enabled, except to power cycle it. And that's rather hard, since it's powering the processor...

One more thing - I _could_ increase the watchdog window, but the maximum I can go to is about 250ms according to the specs. It uses a 1nF capacitor for 50ms, with a maximum of 4.7nF on the datasheet. It would probably work with a larger capacitor but I'm reluctant to go outside of its design specs.

Eek...

Thanks,

Andrew
 
Last edited:
Weeellll I figured it out. In the end, after lots and lots of messing around!

I removed the delays in pins_teensy.c around usb_init() - if anyone else has these issues, I would recommend doing similar. The delays were originally put there to allow slow devices (including Windows USB ports) to initialise. As it happens, USB works fine for me, on a Windows 10 machine, without these delays:

Code:
	delay(10);
	pinMode(2, INPUT_PULLUP);
	pinMode(2, OUTPUT);
	digitalWrite(2, LOW);
	delay(4);
	digitalWrite(2, HIGH);
	pinMode(7, OUTPUT);
	digitalWrite(7, HIGH);
	

	
	//delay(TEENSY_INIT_USB_DELAY_BEFORE);
	usb_init();
	//delay(TEENSY_INIT_USB_DELAY_AFTER);

Also, for those interested, I use INPUT_PULLUP followed by OUTPUT for the pinmodes. This is so as not to unintentionally output a LOW. Not strictly necessary as it turns out, but just something to watch out for. pinmode OUTPUT will set the pin low by default...

Andrew
 
Looking at the startup code, I see that the code hooked into the early_hook by default disables the device watchdog. So any replacement is going to have to do that in addition to whatever else you want to do.
 
The startup_early_hook() - but does not have full Teensy functionality at that point so only selective parts of the MCU are ready for use.

No indication of what code was placed into that local copy of : startup_early_hook()

Unlike those Arduino units that have off chip USB that is 'always there' the Teensy does full speed USB using the MCU chip - so it leaves and returns on programming or restarting. Those delays are there to assure when USB is made active it properly interfaces with whatever HOST ( Windows or other ) as it sees the Teensy appear. Those delays can be excessive but in cases at least some of the delay is needed to allow USB to come up properly, or they would not be there beyond minimizing wait once setup() is entered.

The placement of startup_late_hook() on T_3.x is unfortunately after those waits - that is not the case in Teensy 4.x startup.
 
Thanks guys! Really interesting stuff. I will take another look at startup_early_hook... It seems the examples of using this functionality don't mention the need to disable the watchdog! This must be why, even with an empty startup_early_hook, my teensy seemed to hang.

Given the limited availability of all the MCU features, I think I'll just leave it with my hack of disabling the waits around bringing the USB up. I've always found that I can program the Teensy by pushing the program button, cycling the power and then doing it again. Once my unit is in place, it won't need USB, except for programming.

Even if I did manage to get startup_early_hook to work, I'd need to have it kick off an interrupt-based timer so that I could kick the watchdog within about 50ms as those delays preclude me from doing it any other way. Right now, in the sketch code, I'm just using elapsedMillis to do it. However, that does complicate the programming of the rest of the system as every other operation needs to take less than 50ms. I was considering using an interrupt-based timer to kick the dog, but I think that's going to interfere with SPI comms, for example.

Sorry for the rambling post, but every day is a learning day!

Andrew
 
Actually - would a timer interrupt interfere with SPI comms? Or is it a lower priority? If the timer interrupt occurs, will it wait until other ISR's are serviced? Hmm.... I don't know!

So can I still use a timer interrupt from, say IntervalTimer, and use SPI/CAN bus interrupts?? Would be good if I could!

Andrew
 
Not sure about the priority level of SPI interrupts. General interrupts get set to 'mid level' of #128 and can raised (lower number) or lowered and the number blocks jump by 16 { i.e. 0-15 is the same highest priority). To be sure the timer interrupt could be set with lower priority, but generally the things needing higher pri take it when setup.

As far as interrupts - the priority determines that higher can interrupt lower and those of the same pri wait for each other.
 
Last edited:
Thanks! Good to know some of these details - will definitely help in the case of troubleshooting. I'm just testing SPI and the watchdog together, with watchdog run by IntervalTimer. The two seem to play along nicely together :)

I'd call that a result!

Andrew
 
Hi All,

I've taken another look at this - now I understand why startup_early_hook was hanging - it's because (as rightly stated by @UhClem) that the default start_early_hook disables the chip's watchdog, so I needed to add this code to my own startup_early_hook:

Code:
#if defined(KINETISK)
  WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE;
#elif defined(KINETISL)
  SIM_COPC = 0;  // disable the watchdog
#endif

However, this is not the complete solution... I've managed to figure out a better one...

As a reminder, I need to stroke a watchdog within 50ms of the processor resetting.

So - I added this code to mk20dx128.c:

Line 678(ish):

Code:
static void startup_default_before_usb_hook(void) {}
void startup_before_usb_hook(void)		__attribute__ ((weak, alias("startup_default_before_usb_hook")));

Then (approx) line 1125, just before the call to _init_Teensyduino_internal_():

Code:
startup_before_usb_hook();

Now this will execute code when most things are up and running, but before the USB startup delay (and a few other things).

Then to stroke the dog after a reset, or initialise the watchdog:

Code:
#ifdef __cplusplus
extern "C" {
#endif
void startup_before_usb_hook() {
  // Initialise the watchdog or "stroke" it after a reset
  if (useWD) {
    pinMode(wdiPin, INPUT_PULLUP);
    pinMode(wdiPin, OUTPUT);
    digitalWrite(wdiPin, HIGH);
    wdDelay = 20;
    delay(wdDelay);
    digitalWrite(wdiPin, LOW);
    delay(4);
    digitalWrite(wdiPin, HIGH);    
    myTimer.begin(strokeTheDog, 50000);
  }
  sinceWDI = 0;
}

My timer ISR is this:

Code:
// "Stroke" the watchdog
void strokeTheDog() {
  digitalWrite(ledPin, HIGH);
  if (shouldCrash) return;
  if (sinceLoop > loopTimeOutCheck) return; // Don't stroke the dog if the main program loop is stuck
  digitalWrite(wdiPin, LOW);
  delay(4);
  digitalWrite(wdiPin, HIGH);
  digitalWrite(ledPin, LOW);
}

I'm using the led to test what's going on...

It works perfectly!

I'm now wondering if the startup_before_usb_hook could be added to the core Teensy code? It'd be great to be able to release my code without requiring modifications to the core Teensy definition?

Thanks,

Andrew
 
I should add that neither startup_early_hook, nor startup_late_hook worked for me. Using startup_early_hook, there isn't enough of the Teensy code to enable my timer driven ISR to work. Using startup_late_hook is too late - I _think_ it's after the USB delays...

Andrew
 
Status
Not open for further replies.
Back
Top