Can I not call digitalWrite() before pinMode()?

Hi, I apologize if this has been covered, but I couldn’t find it in the documentation or on this forum. I’m trying to figure out whether calling digitalWrite() before pinMode() is or should be supported.

I have an external peripheral attached to an Electron that has weak pull-ups on some of the control lines so that they default to HIGH upon power up. After booting, I want to change the Electron pins from high impedance to HIGH outputs without glitching these control lines. I might later set them LOW, but I don’t want them to temporarily transition from HIGH->LOW->HIGH as I configure the gpio.

In a non-Arduino environment, I’d enable the peripheral clock for the pin’s port, write a ‘1’ to the pin’s data register bit, and then set the pin to an output. In Particle land, I’d expect this to translate to a call to digitalWrite(HIGH) followed by pinMode(OUTPUT). However, this didn’t work (the pins in question became LOW outputs after the pinMode() call). After inspecting the HAL code, it seems as though only a call to pinMode() will enable the port’s peripheral clock, so calling digitalWrite() before pinMode() won’t work. Thus, I don’t see a way to transition directly from a high-impedance input to a HIGH output.

Is this expected? Is there any other way to achieve what I’m trying to do with the Particle API or will I need to resort to lower-level code?

Would pinSetFast work for you?

https://docs.particle.io/reference/device-os/firmware/electron/#pinsetfast-

I think you would still have to call pinMode first though.

1 Like

I don’t believe so. I think the only way to completely avoid a glitch is to set the port’s data register before the direction register.

I imagine that the API creators didn’t want to burden digitalWrite() with the overhead of checking/enabling the port’s peripheral clock on every call since digitalWrite() might be called frequently in a program. I think that what I need is an API function to enable the peripheral clock separately without calling pinMode(). Then I could call digitalWrite() and subsequently pinMode(). I’m not seeing such a routine though.

Nope, it's not. digitalWrite() performs some sanity checks before actually writing to the port registers and checking the current pin mode is one of these checks.
But yes, pinSetFast() and digitalWriteFast() don't have these checks in place and hence can be used to preset the pin state before actually set it as OUTPUT.

This is exactly how pinSetFast() and digitalWriteFast() work - it sets the data register (specifically the output data register on STM controllers) and then you can set the "direction" register (actually mode register for STM) via pinMode().

However, since you haven't stated which pins you are using you may see that glitch by any means on the pins that act as JTAG pins on boot-up.

Nope, that's exactly what the fast versions are for.

In Arduino land I suspect digitalWrite() also performs sanity checks on each call but you'd use direct port writes for fastest possible access.

But for Particle there is no need to imagine or belief - you can check the implementation here

And here you can see the fast approach

1 Like

Oh interesting. That did seem to work. I had assumed that writing to the port’s data register would be invalid without first enabling the peripheral clock for the port. But, perhaps it was actually the sanity checks in digitalWrite() that were thwarting me. Thanks for the help!

2 Likes