XIAO-ESP32C6 : reading gpio input register

I’m trying to determine the state of a particular pin on my xiao-esp32c6 module without having to use digitalRead(). Instead, I’m hoping that I can examine the bits of the GPIO_INPUT_REG. I wrote code to test this approach as follows:

// Code to read xiao-esp32c6 pin (D3) using register gpio operations

#include <stdint.h>

#define GPIO_IN_REG          0x6009103C
#define GPIO_PIN_D3          21

volatile uint32_t* gpio_in_reg          = (volatile uint32_t*) GPIO_IN_REG;

void setup() {
  pinMode(GPIO_PIN_D3, INPUT);  // Important: sets the IO_MUX correctly
  Serial.begin(115200);
}

void loop() {
  printf("Pin D3 state = %ld\n",*gpio_in_reg);
  delay(1000);
}

I’ve been testing the code by alternatively connecting pin D3 to 3.3 Volts and ground to see if the output numbers change. The results I’ve gotten thus far have me puzzled.

Here are printf outputs corresponding to 3.3V input and grounded input:
14:54:59.275 → Pin D3 state = 287548224
14:55:00.282 → Pin D3 state = 287548224
14:55:01.286 → Pin D3 state = 287548224
14:55:02.290 → Pin D3 state = 285451072
14:55:03.293 → Pin D3 state = 285451072
14:55:04.296 → Pin D3 state = 285451072

Any suggestions as to my code will be much appreciated.

Thanks!

Hi Hubercats,

From my intepretation, the implementation of digitalRead() involves accessing the register tied to a specific pin. So could you please tell me why you want to access the register directly without using digitalRead()? Or the digialRead() function not working for you?

Regards,
John

Hi Hubercats,

Anyway, from the ESP32C6 datasheet (Page 263, Register 7.8 GPIO_IN_REG), the register you are trying to read is a 32-bits register. Intuitively, when you trying to display that value, it might be a 32-bit binary. However, you called ‘printf()’ function which automatically convert binary number to an integer. That is the reason why your output is weird:)

After you convert 287548244 and 285451072 back to binary: they would be
0001 0001 0010 0011 1010 0011 0100 0000
0001 0001 0000 0011 1010 0011 0100 0000
It is clear that the bit 21 has changed from 1 to 0 which means Pin 21 is connected to HIGH and then GND. The result matches exactly with your experiments. So, you are doing the right thing. Congratulations!

Regards,
John

ESP32C6 Datasheet:
https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf#sysreg

2 Likes

Thank you for the detailed analysis and feedback, John!

1 Like

In case helpful to others, below is C code I wrote to read a single GPIO pin on the XIAO-ESP32C6 module.

// Code to read xiao-esp32c6 pin (D3) using register gpio operationd and mask out bit 21

#include <Arduino.h>
#include <stdint.h>
#include <LibPrintf.h>

#define GPIO_IN_REG 0x6009103C    // ESP32C6 GPIO_IN_REG address
#define GPIO_PIN_D3 21

volatile uint32_t* gpio_in_reg = (volatile uint32_t*) GPIO_IN_REG;
uint32_t mask = (1 << GPIO_PIN_D3);  // Extract the 21st bit - i.e., 2^21
uint32_t result;

void setup() {
  pinMode(GPIO_PIN_D3, INPUT);  // Sets the IO_MUX correctly
  Serial.begin(115200);
  delay(100); // Add delay to give library time to initialize
}

void loop() {
  printf("Pin D3 state = %ld\n",*gpio_in_reg);
  //printf("mask = %ld\n",mask);
  result = *gpio_in_reg&mask;
  result = (result >> GPIO_PIN_D3);
  printf("Bit21 = %ld\n\n",result);
  delay(5000);
}
1 Like

Hi EEJim,

My pleasure:)

Regards,
John