defragster
Senior Member+
Below is a sample sketch that shows creation of local hook() functions called before entry to setup as the Reset process proceeds.
It makes some notes on what can be expected to work in each of the three hooks and shows how they can be defined as required "C" code in a C++ sketch.
This sketch records startup time as possible, and there are notes below
It makes some notes on what can be expected to work in each of the three hooks and shows how they can be defined as required "C" code in a C++ sketch.
This sketch records startup time as possible, and there are notes below
Code:
uint32_t gTest[4]; // Global storage test values
uint32_t testLog( uint32_t test ); // Demo storage and use of RAM variables
// These 'hook' functions must be callable from "C" code so: extern "C": Expressed three ways below
// These 'hook' functions are called before setup() - they have progressively more functionality online
// Called from ResetHandler() in ..\hardware\teensy\avr\cores\teensy4\startup.c
// This is "C" code and until setup() is called is it before any C++ constructors have been called
// For example: EEPROM.read(1); // C++ not ready, and this is "C"
extern "C" {
// The early hook MUST be in FLASHMEM - middle/late may as well be as they are only executed once
// Passed parameters and Stack variables only, static and 'global' variables not yet ready
FLASHMEM void startup_early_hook(void) {
testLog( 1 ); // ARM_DWT_CYCCNT not started, and RAM will be cleared
// TOO SOON to call these : Hard Crash and Teensy goes OFFLILNE as CrashReport capture and interrupt vectors not set
// pinMode( 1, OUTPUT );
// digitalWrite( 1, HIGH );
// DMAMEM cache not setup, not configured for use
}
} // extern "C" block
extern "C" void startup_middle_hook(void);
extern "C" volatile uint32_t systick_millis_count;
FLASHMEM void startup_middle_hook(void) {
testLog( 2 );
pinMode( 2, OUTPUT );
digitalWrite( 2, HIGH );
// OPTIONAL FASTER STARTUP: force millis() to be 300 to skip startup delays
// systick_millis_count = 300;
}
extern "C" FLASHMEM void startup_late_hook(void) {
testLog( 3 );
pinMode( 3, OUTPUT );
digitalWrite( 3, HIGH );
}
// There are fixed delays in the Resethandler() to allow USB init to being and other connected devices to power up on cold start
// These are after _middle_ and before _late_ hooks If these values below are #DEFINED for the build the wait times can be changed
// The code above records entry to _middle_ on a T_4.1 with no PSRAM at 1ms to _middle_ and then 300ms to _late_
// With PSRAM it is 327ms on a locked Teensy 4.1 with 1 PSRAM, and 653 ms on an unlocked T_4.1 with (2) PSRAMs
// If NOT predefined when building these values are used in TD 1.57:
// #define TEENSY_INIT_USB_DELAY_BEFORE 20
// #define TEENSY_INIT_USB_DELAY_AFTER 280 // added to above value gives 300 ms
// Shown above in startup_middle_hook() is a systick_millis_count clock advance that will avoid this delay at runtime.
void setup() {
Serial.begin(115200);
while (!Serial && millis() < 4000 );
Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
if ( CrashReport )
Serial.print( CrashReport );
Serial.println( testLog( 4 ) ); // recall 'saved' hook values 1,2,3: values offset for recall +3 and +6
Serial.println( testLog( 7 ) );
Serial.println( testLog( 5 ) );
Serial.println( testLog( 8 ) );
Serial.println( testLog( 6 ) );
Serial.println( testLog( 9 ) );
}
void loop() {
// put your main code here, to run repeatedly:
}
uint32_t testLog( uint32_t test ) { // Demo storage and use of RAM variables
static uint32_t lTest[4];
switch ( test ) {
case 1: // called by _early_
lTest[ test ] = ARM_DWT_CYCCNT + 1; // Still 0, not running - RAM variables not ready for use
gTest[ test ] = millis(); // RAM variables not ready for use
break;
case 2: // called by _middle_
lTest[ test ] = ARM_DWT_CYCCNT; // now running : value stored
gTest[ test ] = millis(); // now running : value stored
break;
case 3: // called by late_
lTest[ test ] = ARM_DWT_CYCCNT; // now running : value stored
gTest[ test ] = millis(); // now running : value stored
break;
case 4:
return lTest[ test - 3 ];
break;
case 5:
return lTest[ test - 3 ];
break;
case 6:
return lTest[ test - 3 ];
break;
case 7:
return gTest[ test - 6 ];
break;
case 8:
return gTest[ test - 6 ];
break;
case 9:
return gTest[ test - 6 ];
break;
}
return 0;
}
Last edited: