Teensy 4.1 Problem setting output pin before its declaration

Hello everyone!

I have a doubt that I can't figure out if it's normal or not:

For hardware reasons I would like to set an output pin to "HIGH" before it is declared as output.

I did this simple program with the Arduino 2 IDE and I notice that the output (connected to a led) does not light up.

If I set the output to "HIGH" after declaring that it is an output, the LED will light up.

void setup() {
digitalWrite(24, HIGH);
pinMode(24, OUTPUT);
}
void loop() {

}

Loading the same program on Arduino (Nano) makes the code work.

I would like to switch from a high impedance state to a "HIGH" state as an output.

NB:

I also tried to search the net, but without finding anything, how all the pins are set when the Teensy 4.1 is turned on and what status they assume when I load a new program.

I've found that pins 24 and 25 become "HIGH" when I load a new program.

Is there a table to figure out what the "HIGH" and "LOW" states of each pin are like?

Thank you all for your help!! :D
 
From the PJRC documentation:
Digital pins may be used to receive signals. Teensy 4.1 pins default to INPUT most with a "keeper" resistor. Teensy 4.1 pins accept 0 to 3.3V signals. The pins are not 5V tolerant. Do not drive any digital pin higher than 3.3V.
You could add an external pull up resistor to the pin of interest. This would override the "keeper" resistor. I don't know if this pulls up, or down.
According to this data sheet the keeper resistor is circa 130kOhms. So a 10k pull up to 3.3V should be OK.
 
Last edited:
Keepers pull both up and down, depending on what the voltage is. That's how they "keep" the pin voltage (stop oscillation or floating behaviour).
 
if you look at the source file https://github.com/PaulStoffregen/cores/blob/master/teensy4/digital.c
you can see @ digitalWrite:
if the pin is a INPUT (as they are at startup)
you write to the pullup/pulldown ctrl register instead of the actual output register.
which are undesired in some situations, think the best would to actually write to both registers if the input is a INPUT
like in the following code:
C++:
void digitalWrite(uint8_t pin, uint8_t val)
{
    const struct digital_pin_bitband_and_config_table_struct *p;
    uint32_t pinmode, mask;

    if (pin >= CORE_NUM_DIGITAL) return;
    p = digital_pin_to_info_PGM + pin;
    pinmode = *(p->reg + 1);
    mask = p->mask;
    if (pinmode & mask) {
        // pin is configured for output mode
        if (val) {
            *(p->reg + 0x21) = mask; // set register
        } else {
            *(p->reg + 0x22) = mask; // clear register
        }
    } else {
        // pin is configured for input mode
        // value controls PULLUP/PULLDOWN resistors
        if (val) {
            *(p->reg + 0x21) = mask; // HERE the set register is also written
            *(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS;
        } else {
            *(p->reg + 0x22) = mask; // HERE the clear register is also written
            *(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(0) | IOMUXC_PAD_HYS;
        }
    }
}

also I think digitalWriteFast do actually write only to the set/clear registers
so you can try that instead
 
Yes, but given that the keepers are circa 130k, they can be overridden by a 10k pull up resistor. You would still be able to use digitalWrite(xx,LOW).
 
Thanks for the help!

I've found that the Teensy 4.1 when booting doesn't immediately enable the declared OUTPUT pins but after some time.

Is there a way to set GPIO pins as OUTPUT with a value of "HIGH" or "LOW" immediately when the microcontroller is turned on?

I made a simple test program where I turn on an LED through a GPIO declared output setting it to "HIGH":

I found that when turned on it stays off and then turns on :(

I need it to turn on right away... Possibly?

Thank you all for the help you are giving me!
 
There are many housekeeping steps performed before setup() is called. The Teensyduino environment has three hook routines that are called before setup(), so you can customize the startup. Here's a posting that describes the hooks: setup hooks
In your case I'd use the "setup_middle_hook()" call, like

Code:
extern "C" void startup_middle_hook(void);
FLASHMEM void startup_middle_hook(void) {
  pinMode(24, OUTPUT);
  digitalWrite(24, HIGH);
}

By using the startup_middle_hook() call you can assert the pin much earlier in the startup process.
 
A question, is it a led you are trying to use or is it some other hardware that need critical startup states?
 
Ci sono molti passaggi di housekeeping da eseguire prima che setup() venga chiamato. L'ambiente Teensyduino ha tre routine hook che vengono chiamate prima di setup(), in modo da poter personalizzare l'avvio. Ecco un post che descrive gli hook: setup hooks
Nel tuo caso userai la chiamata "setup_middle_hook()", come

[CODICE]extern "C" void startup_middle_hook(void);
FLASHMEM void startup_middle_hook(void) {
pinMode(24, USCITA);
digitalWrite(24, ALTO);
}[/CODICE]

Utilizzando la chiamata startup_middle_hook() è possibile attivare il pin molto prima nel processo di avvio.
I'll try it right away!
Thank you!!
 
There are many housekeeping steps performed before setup() is called. The Teensyduino environment has three hook routines that are called before setup(), so you can customize the startup. Here's a posting that describes the hooks: setup hooks
In your case I'd use the "setup_middle_hook()" call, like

Code:
extern "C" void startup_middle_hook(void);
FLASHMEM void startup_middle_hook(void) {
  pinMode(24, OUTPUT);
  digitalWrite(24, HIGH);
}

By using the startup_middle_hook() call you can assert the pin much earlier in the startup process.
I tried the code...
and WORKS !!

The output starts immediately when the Teensy 4.1 is turned on

Question:

What is the term "FLASHMEM" next to the function "void startup_middle_hook(void)"

I tried to remove it and the program works the same...

What do you need?

Thank you very much for your help!!!
 
There are many housekeeping steps performed before setup() is called. The Teensyduino environment has three hook routines that are called before setup(), so you can customize the startup. Here's a posting that describes the hooks: setup hooks
In your case I'd use the "setup_middle_hook()" call, like

Code:
extern "C" void startup_middle_hook(void);
FLASHMEM void startup_middle_hook(void) {
  pinMode(24, OUTPUT);
  digitalWrite(24, HIGH);
}

By using the startup_middle_hook() call you can assert the pin much earlier in the startup process.

Then I discovered that there is still a small problem:

with the two instructions:

Code:
pinMode(24, OUTPUT);
digitalWrite(24, HIGH);

The output changes from "LOW" to "HIGH" for a short period of time.

The problem is that if I connect a 74HC595 shift register and connect the output pin of the Teensy 4.1 to the OE input pin (active low) it happens that by declaring the pin "OUTPUT" it goes "LOW" for a short time and enables the outputs of the 74hc595 component before they are reset.

With the Arduino board to solve this problem just write the inverted instructions:

Code:
digitalWrite(24, HIGH);
pinMode(24, OUTPUT);

In this case, the output is set to "HIGH" before it is declared output.

By doing so, it does not go through a "LOW" and then "HIGH" state but goes directly from high impedance to "HIGH".

This causes the 74HC595 component outputs to be not enabled for a moment.

I tried to run the same code on the Teensy 4.1 but if I set the pin to "HIGH" before I declare it to be an exit pin it doesn't work. :(

Is there a way to fix it?

The 74HC595 component must be reset before enabling its 8 outputs thanks to the OE pin (active low)

It happens that when the Teensy 4.1 turns on it enables its outputs and sets them with a value of "LOW", this causes the 8 outputs of the 74HC595 to be enabled.

I have to make sure that when the Teensy 4.1 is turned on an output pin is in the high impedance state and then directly set to "HIGH" without going through the "LOW" state.

If this happens, you see a flicker or glitch of the 8 outputs of the 74HC595 connected to leds or relays that should not be enabled during power!!
 
Last edited:
A question, is it a led you are trying to use or is it some other hardware that need critical startup states?
The 74HC595 component must be reset before enabling its 8 outputs thanks to the OE pin (active low)

It happens that when the Teensy 4.1 turns on it enables its outputs and sets them with a value of "LOW", this causes the 8 outputs of the 74HC595 to be enabled.

I have to make sure that when the Teensy 4.1 is turned on an output pin is in the high impedance state and then directly set to "HIGH" without going through the "LOW" state.

If this happens, you see a flicker or glitch of the 8 outputs of the 74HC595 connected to leds or relays that should not be enabled during power!!
 
Use a pull up resistor to 3.3V.
It doesn't work because the Teensy 4.1 for a short time declares the output pin with a value of "LOW" then with the oscilloscope I pick up a front that goes from "LOW" to "HIGH".

When I want it to go from "HIGH IMPEDANCE" directly to the "HIGH" state without going through the "LOW" state
 
if you look at the source file https://github.com/PaulStoffregen/cores/blob/master/teensy4/digital.c
you can see @ digitalWrite:
if the pin is a INPUT (as they are at startup)
you write to the pullup/pulldown ctrl register instead of the actual output register.
which are undesired in some situations, think the best would to actually write to both registers if the input is a INPUT
like in the following code:
C++:
void digitalWrite(uint8_t pin, uint8_t val)
{
    const struct digital_pin_bitband_and_config_table_struct *p;
    uint32_t pinmode, mask;

    if (pin >= CORE_NUM_DIGITAL) return;
    p = digital_pin_to_info_PGM + pin;
    pinmode = *(p->reg + 1);
    mask = p->mask;
    if (pinmode & mask) {
        // pin is configured for output mode
        if (val) {
            *(p->reg + 0x21) = mask; // set register
        } else {
            *(p->reg + 0x22) = mask; // clear register
        }
    } else {
        // pin is configured for input mode
        // value controls PULLUP/PULLDOWN resistors
        if (val) {
            *(p->reg + 0x21) = mask; // HERE the set register is also written
            *(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS;
        } else {
            *(p->reg + 0x22) = mask; // HERE the clear register is also written
            *(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(0) | IOMUXC_PAD_HYS;
        }
    }
}

also I think digitalWriteFast do actually write only to the set/clear registers
so you can try that instead
I managed to modify this function in such a way as to write to the output register before the GPIO pin is configured as OUTPUT...

I don't know what I did is correct.

Here is the complete program that controls a 74HC595 without randomly flashing or glitching the outputs on power before it is reset:

Code:
#include "SHOuts_D.h"
extern "C" void startup_middle_hook(void);

//20/09/2022
//Programma TEST per scheda PCB Brown 5*7cm

//Hardware
#define Num_IC 1
#define P_DT 3
#define P_OE 4
#define P_LT 5
#define P_CK 6

#define Time_Speed 150

SHOuts_D SHOuts_A(Num_IC, P_DT, P_CK, P_LT, 1, 1);

FLASHMEM void startup_middle_hook(void) {
  Direct_Write_Out(P_OE, HIGH);
  pinMode(P_OE, OUTPUT);
}

void Direct_Write_Out(uint8_t pin, uint8_t val) {

  const struct digital_pin_bitband_and_config_table_struct *p;

  uint32_t mask;
  //uint32_t pinmode;

  if (pin >= CORE_NUM_DIGITAL) return;
  p = digital_pin_to_info_PGM + pin;
  //pinmode = *(p->reg + 1);
  mask = p->mask;

  // pin is configured for output mode
  if (val) {
    *(p->reg + 0x21) = mask;  // set register
  } else {
    *(p->reg + 0x22) = mask;  // clear register
  }

}

void setup() {

  delay(10);

  delay(500);

  SHOuts_A.clear();
  digitalWrite(P_OE, LOW);

  delay(200);
}

void loop() {

  for (int i = 0; i < 8; i++) {
    SHOuts_A.write(i, 0, HIGH);
    delay(Time_Speed);
  }

  for (int i = 0; i < 8; i++) {
    SHOuts_A.write(i, 0, LOW);
    delay(Time_Speed);
  }

  delay(500);

  for (int i = 0; i < 8; i++) {
    if (i > 0) {
      SHOuts_A.write(i - 1, 0, LOW);
    }
    SHOuts_A.write(i, 0, HIGH);
    delay(Time_Speed);
  }
  SHOuts_A.write(7, 0, LOW);

  delay(500);
}
 
Last edited:
your Direct_Write_Out is correct

but after some research, using:
digitalWriteFast
is doing the same thing as your Direct_Write_Out
i.e. it's writing directly to the set/clear registers regardless of the current pinmode

and as BriComp did say
it's a good measure to allways use external pullup/pulldown resistors (when necessary) to ensure that the signals are at correct levels when the circuit is powered up
 
External pullups/downs won't help with removing a glitch as the mode is changed. If the pin default is to output low when first switched to an output then there will always cause a brief low glitch before the pin can be set high.

As indicated using digitalWriteFast before setting the pin to an output will work, this optimises down to a single processor instruction setting the register. However it is only intended to be used with constant pin assignments, if the pin number is variable then you will need to use something like your function to map from Teensy pin number to physical pin register and set the appropriate bit that way.

So you need to do both, add an external pullup to set the pin state while it is acting as an input and then use digitalWriteFast, or some other method, to set the output state before setting the pin as an output.

Question:

What is the term "FLASHMEM" next to the function "void startup_middle_hook(void)"

I tried to remove it and the program works the same...

What do you need?

FLASHMEM tells the compiler/linker to leave that bit of code in flash and execute it from there. Without this the default is to copy the code to RAM1 memory on startup and run it from that location. If has no impact on the logical functionality but the memory usage numbers and speed will be slightly different.

Running from RAM is significantly faster but you only have limited RAM1 which is shared between user code and any local variables. As a general rule any non-speed critical startup code should be put in FLASHMEM, any code used in loop() should not use this so that it goes in RAM and gains the performance boost.
There are whole threads on how best to allocation things between the 4 possible memory regions on the Teensy (there is also non-cacheable RAM (DMAMEM) and optional external SPI ram (EXTMEM)). It can get complicated.

The TL:DR version is that unless you are doing something performance critical or running up against the memory size limits the defaults are probably the best option but anything else that compiles will probably work just as well.
 
External pullups/downs won't help with removing a glitch as the mode is changed. If the pin default is to output low when first switched to an output then there will always cause a brief low glitch before the pin can be set high.

As indicated using digitalWriteFast before setting the pin to an output will work, this optimises down to a single processor instruction setting the register. However it is only intended to be used with constant pin assignments, if the pin number is variable then you will need to use something like your function to map from Teensy pin number to physical pin register and set the appropriate bit that way.

So you need to do both, add an external pullup to set the pin state while it is acting as an input and then use digitalWriteFast, or some other method, to set the output state before setting the pin as an output.



FLASHMEM tells the compiler/linker to leave that bit of code in flash and execute it from there. Without this the default is to copy the code to RAM1 memory on startup and run it from that location. If has no impact on the logical functionality but the memory usage numbers and speed will be slightly different.

Running from RAM is significantly faster but you only have limited RAM1 which is shared between user code and any local variables. As a general rule any non-speed critical startup code should be put in FLASHMEM, any code used in loop() should not use this so that it goes in RAM and gains the performance boost.
There are whole threads on how best to allocation things between the 4 possible memory regions on the Teensy (there is also non-cacheable RAM (DMAMEM) and optional external SPI ram (EXTMEM)). It can get complicated.

The TL:DR version is that unless you are doing something performance critical or running up against the memory size limits the defaults are probably the best option but anything else that compiles will probably work just as well.
Interesting!

So if I create a function with the FLASHMEM instruction is it stored in flash memory instead of RAM?

Can I use this statement to create functions that don't run fast but only once?

Example:

Code:
void setup(){

}

void loop(){

 Process();

}

FLASHMEM void Process(){
 
 //CODE

}
 
Sorry if I wasn't clear. It doesn't cause the code to only be run once. it is normally used for code that will only ever be run once because that's how the program is written.

FLASHMEM has no impact on the logical execution of the program, all it changes is where in memory the code is stored. In your example including FLASHMEM in the definition of Process will simply slow the program down, it will still be run once per time around the loop.

It's normally used for setup related functions which are only used once and so the speed penalty is not important, people rarely care if the program takes a few ms longer to start up.

The only time you'd want to do something like your example is if speed wasn't important, you were running out of RAM, and Process contained a lot of code.
 
Can I use this statement to create functions that don't run fast but only once?

No. Use of FLASHMEM only affects which type of memory is used.

It doesn't alter how many times a function runs. The only effect is how much memory is used, and a (usually minor) change in the speed your program runs.

Normally you would choose certain functions for FLASHMEM because you don't mind if they take longer to run. A common choice is code that initializes stuff. But YOU are the one who makes these decisions. You would choose a function to run from slower flash memory because you know it only runs once at startup (and presumably you don't mind if startup is slightly slower because you care about the speed after everything is running). The number of times a function runs doesn't change because of FLASHMEM. You decide whether to use FLASHMEM based on your knowledge of how the code will run. Functions that you know will run only once are a common choice. But it is ultimately up to you to make those choices.

But you might actually care deeply about how quickly single-use initialization runs. Perhaps your application is special where you're responding to some time-critical event that caused the hardware to reboot or run different stuff and you need to quickly initialize a lot of variables or special hardware before you can do the timing-critical thing. In that sort of application, perhaps you would choose to use FLASHMEM on other functions that run repetitively, but perhaps do less critical functions like monitor hardware running normally. Only you understand the needs of your specific application. You decide which functions to use as FLASHMEM with your own human decisions based on your priorities.
 
Last edited:
No. L'uso di FLASHMEM influenza solo il tipo di memoria utilizzato.

Non modificare il numero di volte in cui viene eseguita una funzione. L'unico effetto è la quantità di memoria utilizzata e una modifica (solitamente minima) nella velocità di esecuzione del programma.

Di solito scegli determinate funzioni per FLASHMEM perché non ti dispiacerebbe se impiegassero più tempo per essere eseguite. Una scelta comune è il codice che inizializza le cose. Ma sei TU che prendi queste decisioni. Scegli una funzione da eseguire nella memoria flash più lenta perché sai che viene eseguita solo una volta all'avvio (e presumibilmente non ti dispiacerebbe se l'avvio fosse leggermente più lento perché ti interessa la velocità dopo che tutto è in esecuzione). Il numero di volte in cui viene eseguita una funzione non cambia a causa di FLASHMEM. Decidi se usare FLASHMEM in base alle tue conoscenze di come verrà eseguito il codice. Le funzioni che verranno eseguite solo una volta sono una scelta comune. Ma alla fine spetta a te fare queste scelte.

Ma potresti effettivamente preoccuparti molto della rapidità con cui viene eseguita l'inizializzazione monouso. Forse la tua applicazione è speciale, in quanto stai rispondendo a un evento critico per il tempo che ha causato il riavvio dell'hardware o l'esecuzione di cose diverse e hai bisogno di inizializzare rapidamente molte variabili o hardware speciale prima di poter fare la cosa critica per il tempo. In quel tipo di applicazione, forse sceglieresti di usare FLASHMEM su altre funzioni che vengono eseguite ripetutamente, ma forse esegui funzioni meno critiche come il monitoraggio dell'hardware che funziona normalmente. Solo tu capisci le esigenze della tua applicazione specifica. Decidi quali funzioni usare come FLASHMEM con le tue decisioni umane in base alle tue priorità.
Ohhhhhhhhhhh:D

Grazie mille per l'informazione!
 
Last edited:
Back
Top