Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 1 of 1

Thread: Teensy 4.x Hooks before setup()

  1. #1
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,476

    Teensy 4.x Hooks before setup()

    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

    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"
    // 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
      }
    
      FLASHMEM void startup_middle_hook(void) {
        testLog( 2 );
        pinMode( 2, OUTPUT );
        digitalWrite( 2, HIGH );
      }
    } // extern "C" block
    
    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
    
    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 by defragster; 08-11-2022 at 09:37 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •