Answers checklist.
IDF version.
release/v5.0 11c59a2
Operating System used.
Linux
How did you build your project?
Command line with idf.py
If you are using Windows, please specify command line type.
None
Development Kit.
Custom board
Power Supply used.
USB
What is the expected behavior?
GPIO inputs should correctly report bus level.
What is the actual behavior?
GPIO reads from the ULP are only reporting a 1.
Steps to reproduce.
I'm bit-banging I2C to talk to an SHT40 temperature sensor. ULP GPIO is set to open drain with both input and output enabled. I am able to correctly write to the SHT40 and the SHT40 responds correctly. All signals have been verified with a bus analyzer - everything there is working properly on both reads and writes.
However, the GPIO level reported by the ulp_riscv_gpio_get_level() is returning only 1s. Thus, while my I2C writes are correct and the read data returned by the SHT40 are correct, the input level reported by the ESP32 itself is incorrect.
According to the DS18B20 ULP example, this exact use case is possible: both input and output enabled in open drain mode.
Note that the ULP GPIO API is completely undocumented. I don't know if there are any special considerations needed to make this work, because none are documented. The register level documentation in the technical reference manual is similarly useless. The logic diagram does indicate this functionality should be possible - assuming the diagram is accurate.
I have also verified this behavior with a simple IO level check: Drive a 1 and ground the pin. I verified the pin itself is pulled to 0V via DMM, however, the ULP is reporting a 1.
Here's my IO init code:
ulp_riscv_gpio_init( I2C_GPIO_SDA );
ulp_riscv_gpio_init( I2C_GPIO_SCL );
ulp_riscv_gpio_output_enable( I2C_GPIO_SDA );
ulp_riscv_gpio_output_enable( I2C_GPIO_SCL );
ulp_riscv_gpio_input_enable( I2C_GPIO_SDA );
ulp_riscv_gpio_input_enable( I2C_GPIO_SCL );
ulp_riscv_gpio_set_output_mode( I2C_GPIO_SDA, RTCIO_MODE_OUTPUT_OD );
ulp_riscv_gpio_set_output_mode( I2C_GPIO_SCL, RTCIO_MODE_OUTPUT_OD );
ulp_riscv_gpio_output_level( I2C_GPIO_SDA, 1 );
ulp_riscv_gpio_output_level( I2C_GPIO_SCL, 1 );
And the check code:
ulp_riscv_gpio_output_level( I2C_GPIO_SDA, 0 );
delay_us(1);
gpio_low = ulp_riscv_gpio_get_level( I2C_GPIO_SDA );
ulp_riscv_gpio_output_level( I2C_GPIO_SDA, 1 );
delay_us(1);
gpio_high = ulp_riscv_gpio_get_level( I2C_GPIO_SDA );
gpio_high will read a 1 regardless of the actual voltage on the pin. It will correctly drive a 1, but if pulled down, will still read 1. It must be reporting the selected output level, as gpio_low will correctly report a 0 (and 0 is what the pin is actually driven to).
Debug Logs.
No response
More Information.
No response
Answers checklist.
IDF version.
release/v5.0 11c59a2
Operating System used.
Linux
How did you build your project?
Command line with idf.py
If you are using Windows, please specify command line type.
None
Development Kit.
Custom board
Power Supply used.
USB
What is the expected behavior?
GPIO inputs should correctly report bus level.
What is the actual behavior?
GPIO reads from the ULP are only reporting a 1.
Steps to reproduce.
I'm bit-banging I2C to talk to an SHT40 temperature sensor. ULP GPIO is set to open drain with both input and output enabled. I am able to correctly write to the SHT40 and the SHT40 responds correctly. All signals have been verified with a bus analyzer - everything there is working properly on both reads and writes.
However, the GPIO level reported by the ulp_riscv_gpio_get_level() is returning only 1s. Thus, while my I2C writes are correct and the read data returned by the SHT40 are correct, the input level reported by the ESP32 itself is incorrect.
According to the DS18B20 ULP example, this exact use case is possible: both input and output enabled in open drain mode.
Note that the ULP GPIO API is completely undocumented. I don't know if there are any special considerations needed to make this work, because none are documented. The register level documentation in the technical reference manual is similarly useless. The logic diagram does indicate this functionality should be possible - assuming the diagram is accurate.
I have also verified this behavior with a simple IO level check: Drive a 1 and ground the pin. I verified the pin itself is pulled to 0V via DMM, however, the ULP is reporting a 1.
Here's my IO init code:
And the check code:
gpio_high will read a 1 regardless of the actual voltage on the pin. It will correctly drive a 1, but if pulled down, will still read 1. It must be reporting the selected output level, as gpio_low will correctly report a 0 (and 0 is what the pin is actually driven to).
Debug Logs.
No response
More Information.
No response