Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should be possible to digitalRead() a pin that's not GPIO #10370

Closed
1 task done
egnor opened this issue Sep 24, 2024 · 11 comments
Closed
1 task done

Should be possible to digitalRead() a pin that's not GPIO #10370

egnor opened this issue Sep 24, 2024 · 11 comments
Assignees
Labels
Status: Awaiting triage Issue is waiting for triage

Comments

@egnor
Copy link
Contributor

egnor commented Sep 24, 2024

Board

All

Device Description

Any device

Hardware Configuration

Any configuration

Version

latest master (checkout manually)

IDE Name

any IDE

Operating System

any OS

Flash frequency

any frequency

PSRAM enabled

yes

Upload speed

any

Description

in arduino-esp32 3.x, if you attempt to digitalRead() from a pin that's been configured as another peripheral (e.g. I2C or UART), an error message comes back like

[4629150][E][esp32-hal-gpio.c:190] __digitalRead(): IO 16 is not set as GPIO.

and the function always returns 0. in previous versions it was possible to see the state of the pin regardless of what peripheral is driving it (which is perfectly well supported by hardware). there are a number of use cases for this, for monitoring what a peripheral is actually doing, for seeing if something externally is overriding it, etc..

the code in question is here:

if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) != NULL) {

(as far as I know, gpio_get_level() will always work even if the pin is driven by another peripheral, so I think the check can just be skipped?) if the change is intentional, it should probably be put in the migration document??

Sketch

void setup() {
  Serial.begin(115200);
  I2C.begin();
}

void loop() {
  delay(500);
  Serial.println(digitalRead(SDA));
}

Debug Message

[5220153][E][esp32-hal-gpio.c:190] __digitalRead(): IO 16 is not set as GPIO.

(actual pin number may vary of course)

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.
@egnor egnor added the Status: Awaiting triage Issue is waiting for triage label Sep 24, 2024
@P-R-O-C-H-Y
Copy link
Member

P-R-O-C-H-Y commented Sep 24, 2024

Hi @egnor, can you please give it a test without the check if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) != NULL) {
if it works as you expect? There is also this note in gpio.h file in IDF for gpio_get_level():
@warning If the pad is not configured for input (or input and output) the returned value is always 0.

So this may work for some pins of peripherals, but may not for everything.

PS: Thanks for very nice report.

@P-R-O-C-H-Y P-R-O-C-H-Y self-assigned this Sep 24, 2024
@vvb333007
Copy link

Similar issue with pinMode():
I am trying to set OUTPUT ENABLE on a reserved pin 6 (used internally for SPI) on my ESP32 Devkit. If I do it with IDF functions then it is all fine. But if I call pinMode() then it all goes through periman, causing pin deinit function to be called, pin getting reconfigured eventually leading to system crash and reboot. Yes I understand that I am doing dangerous stuff, but IDF allows for it so why pinMode() doesn't.. But as I can understand it all requires a massive periman logic change :(

@P-R-O-C-H-Y
Copy link
Member

P-R-O-C-H-Y commented Oct 7, 2024

@vvb333007 What is the point of setting OUTPUT ENABLE on internally used pin for SPI (just curious)?
You can always you Arduino as a IDF component if you need to do something specific or more detailed stuff.
The Permian is working really well of handling pins between peripherals. With logic of peripheral manager you can use same pin for multiple peripherals at the same time.

Did you have any time to properly test the gpio_get_level() as I asked in previous comment?

@vvb333007
Copy link

vvb333007 commented Oct 8, 2024

Yes it works if periman call is commented.

I am just thinking that pinMode() must not call deinit when I just want to add 1 more flag, and do not reconfigure pin to GPIO funxtion.

If I am manipulating flags on live UART TX pin for example I want that pin to remain UART TX, not switch to GPIO.
Currently I use IDF functions for that, so it is not a big deal.

As I see it that digitalWrite() is the function which must check the bus type and reconfigure pin to GPIO function on attempt to set digital value.

Did you have any time to properly test the gpio_get_level() as I asked in previous comment?

@vvb333007
Copy link

vvb333007 commented Oct 8, 2024

@vvb333007 What is the point of setting OUTPUT ENABLE on internally used pin for SPI (just curious)?

I am making a shell (a devel/debug tool) which among other things provides commands for pin manipulation. While I was
playing with it I suddenly discovered that pinMode(6, OUTPUT|INPUT|PULL_UP) causes system crash.

I know that pin 6 is used internally for the memory access but still.. It is just only 1 flag was updated, other flags remain unchanged and it crashed. I looked into it and found that idf functions alone do not crash the whole sketch. Then I found this bug report and thats why I posted it here.

Thats the full story.

@vvb333007
Copy link

Did you have any time to properly test the gpio_get_level() as I asked in previous comment?

Another thing to consider:

By default, many pins of ESP32 are routed through IO MUX and have function of GPIO. Such pins are ready to be used, however
Periman marks them as being in INIT state. As result digitalRead() or digitalWrite() are not working. If, however, I call pinMode(.., INPUT), then pin gets reconfigured: now it is routed through GPIO Matrix and have a function of "simple GPIO input".

As such you are not able to digitalRead() interface pin (uart for example): it is either not readable because of what is said in the very first message, or it loses its IOMUX function (being uart_tx for example) because of pinMode(...).

But yes as you just said anyone can simply use IDF function in their Arduino sketch to do such a specific stuff.

Just a thought.
May be Periman should not mark GPIO pins as INIT if they are already configured as "GPIO" via IO_MUX?

@SinekaRamu
Copy link

Hi @P-R-O-C-H-Y, Issue with Using SD Card GPIO Pins on ESP32-CAM

I am working with the ESP32-CAM and trying to use GPIO pins that are normally allocated for the SD card (e.g., GPIOs 2, 4, 12, 13, 14, 15) as general-purpose GPIOs. However, I am not using an SD card in my project and have ensured that the SD card functionality is not initialized in my code.

Despite this, I encounter the following error:
[ 979][E][esp32-hal-gpio.c:190] __digitalRead(): IO 15 is not set as GPIO.

Is there a way to configure or free up these GPIO pins for general-purpose use on the ESP32-CAM?

Thanks in advance for your help!

@P-R-O-C-H-Y
Copy link
Member

Hi @P-R-O-C-H-Y, Issue with Using SD Card GPIO Pins on ESP32-CAM

I am working with the ESP32-CAM and trying to use GPIO pins that are normally allocated for the SD card (e.g., GPIOs 2, 4, 12, 13, 14, 15) as general-purpose GPIOs. However, I am not using an SD card in my project and have ensured that the SD card functionality is not initialized in my code.

Despite this, I encounter the following error: [ 979][E][esp32-hal-gpio.c:190] __digitalRead(): IO 15 is not set as GPIO.

Is there a way to configure or free up these GPIO pins for general-purpose use on the ESP32-CAM?

Thanks in advance for your help!

Hi @SinekaRamu, first you need to call a pinMode() function to set it as a GPIO pin. Check the docs here.

@SinekaRamu
Copy link

SinekaRamu commented Jan 7, 2025

Hi @SinekaRamu, first you need to call a pinMode() function to set it as a GPIO pin. Check the docs here.

pinmode for OUTPUT is working fine, While defining a input pin it gives wired output

`
void setup() {
Serial.begin(115200);
pinMode(2, INPUT);
}

void loop() {
Serial.println("testing"+ digitalRead(2));
delay(1000);
}
`
while OFF = testing
while ON = esting
I did get the value like 0 or 1.

@rkalwak
Copy link

rkalwak commented Feb 2, 2025

Hi @P-R-O-C-H-Y ,

I followed the idea with setting the pinMode but it doesn't help either I set INPUT nor OUTPUT.

There is a lib for CC1101 radio which stopped working after switching to new boards, in which there are actual calls for digitalRead from MISO pin:
https://github.com/LSatan/SmartRC-CC1101-Driver-Lib/blob/b8c6af4c7c2214cd77a4e9b2e2cb37b24b393605/ELECHOUSE_CC1101_SRC_DRV.cpp#L147

I am using the most popular WROOM based dev kit, where pin number 19 is a hardware MISO pin, so usage of it is intended. It is also listed as GPIO pin.
https://www.electronicshub.org/wp-content/smush-webp/2021/02/ESP32-Pinout-1.jpg.webp

We are using this lib for reading from WMBUS water meters in Supla software, which unfortunately had to move forward with boards.

Do you have any other workaround or is there a chance to make it working as with boards 2.x.x?

Best regards
Rafał

@Jason2866
Copy link
Collaborator

Solved with #11016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Awaiting triage Issue is waiting for triage
Projects
None yet
Development

No branches or pull requests

6 participants