Page 1 of 1

ESP32 GPIO function configuration via configuration registers.

Posted: Sun Nov 28, 2021 8:43 pm
by Ciro Bruno
Hello all

I've been using ESP32 for a couple of years, mostly through Arduino IDE. Since July I've been using exclusively VSCode + PlatformIO with Arduino framework. My reason for changing has been the interruption of support to SPIFFS in the latest Arduino IDE versions.

Nevertheless, now I'm facing difficulties for setting up GPIO 12 and 13 as INPUT_PULLUP in a ESP32-Pico-D4. I've been using

Code: Select all

pinMode( 12, INPUT_PULLUP);
, but this always return 0 (false), as well as trying to set it as INPUT or INPUT_PULLDOWN. Browsing some discussions in the internet I found out that the default Arduino framework version used by VSCode is outdated and has issues regarding some GPIO pins configuration.

So, I'd like to use the safest solution for this issue, that is configuring these GPIOs directly through configuration registers.

I've been reading chapter 5 of esp32_technical_reference_manual_en.pdf, but I didn't understand what to do. Maybe I need to understand better the microprocessor's architecture itself.

Anyway, I'd like to count on your help for:

item 1) setting up GPIO12 and GPIO13 as inputs with pullup, through writing on configuration registers;
item 2) understanding better how attribute functions to GPIO pads.

I'd like to start by item 1, making GPIO 12 and 13 behave as INPUT_PULLUP by writing on the proper configuration registers. Then, I'd like to play with other basic IO functions, like INPUT_PULLDOWN, INPUT and OUTPUT.

Later (item 2, I'd like to go through an overview of the GPIOs related registers, from a single GPIO pad toward a specific embedded function.

Starting from Figure 7 ("IO_MUX, RTC IO_MUX and GPIO Matrix Overview") on page 47, I'd like to understand where I should find the simple digital IOs, such as those accessible through "digitalRead" or "digitalWrite".
2.1) Are these ones are considered as "peripherals" or not? I can't identify them in the diagram.
2.2) Should they be treated attached directly to IO_MUX or via GPIO Matrix?
2.3) This Figure also shows "34 GPIOs" between "GPIO Matrix" and "IO_MUX". Isn't 34 the same number of GPIO pads? Is it a coincidence or is this label ("34 GPIOs") misplaced in the diagram?

Image

Thank you.
Best regards,
Ciro.

Re: ESP32 GPIO function configuration via configuration registers.

Posted: Mon Nov 29, 2021 6:32 am
by boarchuz
Ciro Bruno wrote:
Sun Nov 28, 2021 8:43 pm
I've been using

Code: Select all

pinMode( 12, INPUT_PULLUP);
, but this always return 0 (false)
pinMode is void:
https://github.com/espressif/arduino-es ... gpio.h#L88
Do you mean that reading the pin level (ie. with digitalRead(12)) afterwards always returns 0?

Check your particular board's schematic to ensure 12 isn't used for something else, disconnect any external modules/LEDs/resistors/etc, and check the voltage on 12 with your multimeter. Do the same with a different pin (eg. 25 or 32).

Re: ESP32 GPIO function configuration via configuration registers.

Posted: Wed Dec 01, 2021 10:10 pm
by Ciro Bruno
Hi

Thank you for your attention

Indeed I've already checked all electronic signals, comparing GPIOs 12 and 13 to GPIO25.

Configuring all them as INPUT_PULLUP, GPIO25 holds close to 3.3v, while GPIO 12 and 13 keep around 0.3v.

Keeping them loose and reading them with "digitalRead()", GPIO25 keeps boolean 1 state, while GPIOs 12 and 13 never leave boolean 0.

When grounding them, one at once, GPIO25 returns boolean 0, as expected.

Reading GPIO with "touchRead()", GPIOs 12 and 13 show values between 22 and 48 when loose, falling to 0 when grounded. This is the only life signal these pins show.

All this happens when compiling and flashing with VSCode.

When compile and flashing with Arduino IDE 2.0.0, these pins work perfectly as expected.

So, I guess there should be no doubt about hardware integrity. That's why I'm looking for solving that through configuration registers.

Regards,

Re: ESP32 GPIO function configuration via configuration registers.

Posted: Sun Dec 05, 2021 9:06 pm
by Ciro Bruno
Again, trying to find out how to configure digital inputs and output through ports registers, I've been trying to apply "pinMode" commands to three different GPIOs and check its effect over some registers. But regardless the pin mode selected, it seems I'm watching the wrong registers.

The code I've been using is:

Code: Select all

uint8_t fase = 0;
  #define output          0
  #define input           1
  #define input_pulldown  2
  #define input_pullup    3

void print_reg(void)
{
  Serial.print("\nGPIO_IN_REG : 0b");       Serial.print(GPIO_IN_REG, BIN);
  Serial.print("\tGPIO_ENABLE_REG : 0b");   Serial.print(GPIO_ENABLE_REG, BIN);
  Serial.print("\tIO_MUX_GPIO25_REG : 0b"); Serial.print(IO_MUX_GPIO25_REG, BIN);
  Serial.print("\tIO_MUX_GPIO12_REG : 0b"); Serial.print(IO_MUX_GPIO12_REG, BIN);
  Serial.print("\tIO_MUX_GPIO13_REG : 0b"); Serial.print(IO_MUX_GPIO13_REG, BIN);
}

void setup (void)
{
  Serial.begin(115200);
  delay(500);
  Serial.print("Configuração inicial:");
  print_reg();
}

void loop (void)
{
  switch (fase) {
    case output:
      pinMode(25, OUTPUT);  pinMode(12, OUTPUT);  pinMode(13, OUTPUT);
      Serial.print("\nOUTPUT:");
      break;
     case input:
      pinMode(25, INPUT);   pinMode(12, INPUT);   pinMode(13, INPUT);
      Serial.print("\nINPUT:");
      break;
     case input_pulldown:
      pinMode(25, INPUT_PULLDOWN);  pinMode(12, INPUT_PULLDOWN);  pinMode(13, INPUT_PULLDOWN);
      Serial.print("\nINPUT_PULLDOWN:");
      break;
     case input_pullup:
      pinMode(25, INPUT_PULLUP);    pinMode(12, INPUT_PULLUP);    pinMode(13, INPUT_PULLUP);
      Serial.print("\nINPUT_PULLUP:");
      break;
    default: break;
  }
  
  delay(1000);

  print_reg();

  if (++fase > 3) fase = 0;
}
And the results I've been cyclically obtaining are:

Code: Select all

OUTPUT:
GPIO_IN_REG : 0b111111111101000100000000111100	GPIO_ENABLE_REG : 0b111111111101000100000000100000	IO_MUX_GPIO25_REG : 0b111111111101001001000000100100	IO_MUX_GPIO12_REG :0b111111111101001001000000110100	IO_MUX_GPIO13_REG : 0b111111111101001001000000111000
INPUT:
GPIO_IN_REG : 0b111111111101000100000000111100	GPIO_ENABLE_REG : 0b111111111101000100000000100000	IO_MUX_GPIO25_REG : 0b111111111101001001000000100100	IO_MUX_GPIO12_REG : 0b111111111101001001000000110100	IO_MUX_GPIO13_REG : 0b111111111101001001000000111000
INPUT_PULLDOWN:
GPIO_IN_REG : 0b111111111101000100000000111100	GPIO_ENABLE_REG : 0b111111111101000100000000100000	IO_MUX_GPIO25_REG : 0b111111111101001001000000100100	IO_MUX_GPIO12_REG : 0b111111111101001001000000110100	IO_MUX_GPIO13_REG : 0b111111111101001001000000111000
INPUT_PULLUP:
GPIO_IN_REG : 0b111111111101000100000000111100	GPIO_ENABLE_REG : 0b111111111101000100000000100000	IO_MUX_GPIO25_REG : 0b111111111101001001000000100100	IO_MUX_GPIO12_REG : 0b111111111101001001000000110100	IO_MUX_GPIO13_REG : 0b111111111101001001000000111000
This code has run in Arduino 2.0.0-beta.7

Given these results, which might be the registers affected by "pinMode" command?

Please help.
Thank you.
Regards,
Ciro.

Re: ESP32 GPIO function configuration via configuration registers.

Posted: Tue Dec 14, 2021 2:27 pm
by Ciro Bruno
The matter here it that the compiler doesn’t allow the register to be read or written as a variable.


ciro_bruno:
Serial.print(GPIO_IN_REG, BIN);
So, doing so I can get just the register’s address itself (0b111111111101000100000000111100).

As far as I can remember, in Arduino environment it is/was possible to read and write directly on the registers through their mnemonics.

Anyway, I guess I’ve got to find out another way.

I’ve been thinking of doing so via pointers. I’ve been trying, but I haven’t been able to attribute the register’s address (a constant) to the pointer . Neither can read the address the pointer points to.

Code: Select all

  uint32_t conteudo;
  uint32_t *reg_PTN;

  reg_PTN = (uint32_t) GPIO_ENABLE_REG; //  #define GPIO_ENABLE_REG (DR_REG_GPIO_BASE + 0x0020) | #define DR_REG_GPIO_BASE 0x3ff44000
  conteudo = *reg_PTN;

  Serial.print("\nGPIO_ENABLE_REG = 0x"); Serial.print( reg_PTN, HEX);
  Serial.print("\tConteudo = 0b"); Serial.print (*reg_PTN, BIN);
The error messages are:

Code: Select all

src\main.cpp:8:11: error: invalid conversion from 'uint32_t {aka unsigned int}' to 'uint32_t* {aka unsigned int*}' [-fpermissive]
   reg_PTN = (uint32_t) GPIO_ENABLE_REG; //  #define GPIO_ENABLE_REG (DR_REG_GPIO_BASE + 0x0020) | #define DR_REG_GPIO_BASE 0x3ff44000   
           ^
src\main.cpp:11:69: error: no matching function for call to 'print(uint32_t*&, int)'
   Serial.print("\nGPIO_ENABLE_REG = 0x"); Serial.print( reg_PTN, HEX);
                                                                     ^
So, how could I give this pointer the register’s address?

Thank you.
Regards,
Ciro.