Unpredictable GPIO inputs behavior

Vilius
Posts: 26
Joined: Mon Nov 13, 2023 9:22 am

Unpredictable GPIO inputs behavior

Postby Vilius » Thu Dec 07, 2023 12:06 pm

Hi,

I am developing a product that includes using fast ADC with ESP32 (I am using Ethernet kit board with WROOVER - E model). I am using ADC12020 which has 12 bit parallel outputs. I am aiming for sample frequency above 1 MSPS so, gpio_get/set_level commands does not do it for me (I developed a parallel gpio read code, also I am generating the clock for the ADC with my ESP gpio output using low level commands)... I am getting very strange readings, and ADC has nothing to do with it this time...

For the testing, I physically disconnect everything from the ESP board and I enable the pull-down resistors in the setup. However, I still get unexplainable readings of 2699 every cycle... (this translates to 1010 1000 1011 reading from MSB to LSB, but even my multimeter shows, that every single pin is at 0 volts.) Just for clarification, I have increased the watchdog timer interval to 11000 ms in the menuconfig, I dont know if this makes any difference, but other than that I have absolutely no clue what the problem could be...

I am aware that some pins have reserved functions, but I only use the pins that are routed to the devboard pin headers, I guess its extremely unlikely for the manufacturer to put such pins in the pin header row...

Any ideas what could be causing this mad behavior of GPIO?

Code: Select all

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "soc/soc.h"
#include "soc/gpio_struct.h"
#include "soc/gpio_reg.h"
#include "esp32/rom/ets_sys.h"
#include "soc/rtc.h"

#define INTERRUPT_INPUT 15
#define GPIO_CLOCK 14 
#define NUM_GPIO_PINS 12
#define NUM_CYCLES 100

#define GPIO_PIN_12 12   //LSB
#define GPIO_PIN_13 13
#define GPIO_PIN_2 2
#define GPIO_PIN_4 4
#define GPIO_PIN_16 16
#define GPIO_PIN_17 17
#define GPIO_PIN_32 32
#define GPIO_PIN_33 33
#define GPIO_PIN_34 34
#define GPIO_PIN_35 35
#define GPIO_PIN_36 36
#define GPIO_PIN_39 39   //MSB

const uint32_t gpio_pins[NUM_GPIO_PINS] = {
    12, 13, 2, 4, 16, 17, 32, 33, 34, 35, 36, 39
};

static const gpio_num_t GPIO_PINS[NUM_GPIO_PINS] = {
    GPIO_PIN_12, GPIO_PIN_13, GPIO_PIN_2, GPIO_PIN_4,
    GPIO_PIN_16, GPIO_PIN_17, GPIO_PIN_32, GPIO_PIN_33,
    GPIO_PIN_34, GPIO_PIN_35, GPIO_PIN_36, GPIO_PIN_39
};

bool trigger = false;
uint16_t data_array[NUM_CYCLES] = {0};

static void IRAM_ATTR gpio_interrupt_handler(void *args)
{
    trigger = true;
}

void disableWatchdog()
{
    WRITE_PERI_REG(RTC_CNTL_WDTCONFIG0_REG, 0);
    WRITE_PERI_REG(RTC_CNTL_WDTCONFIG1_REG, 0);
}



void app_main()
{
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    esp_rom_gpio_pad_select_gpio(INTERRUPT_INPUT);
    gpio_set_direction(INTERRUPT_INPUT, GPIO_MODE_INPUT);
    gpio_pulldown_en(INTERRUPT_INPUT);
    gpio_pullup_dis(INTERRUPT_INPUT);
    gpio_set_intr_type(INTERRUPT_INPUT, GPIO_INTR_POSEDGE);

    gpio_install_isr_service(0);
    gpio_isr_handler_add(INTERRUPT_INPUT, gpio_interrupt_handler, (void *)INTERRUPT_INPUT);

    gpio_config_t io_conf_output = {
        .pin_bit_mask = (1ULL << GPIO_CLOCK),
        .mode = GPIO_MODE_OUTPUT,
    };
    gpio_config(&io_conf_output);

    gpio_config_t io_conf;
    for (int i = 0; i < NUM_GPIO_PINS; ++i)
    {
        io_conf = (gpio_config_t){
            .pin_bit_mask = (1ULL << GPIO_PINS[i]),
            .mode = GPIO_MODE_INPUT,
            .intr_type = GPIO_INTR_DISABLE,
            .pull_up_en = GPIO_PULLUP_DISABLE,
            .pull_down_en = GPIO_PULLDOWN_ENABLE,  // Enable pulldown resistors
        };
        gpio_config(&io_conf);
    }

    uint16_t gpio_inputs;
    disableWatchdog();
    int k = 0;

    while (1)
    {
        REG_WRITE(GPIO_OUT_W1TS_REG, (1 << GPIO_CLOCK));
        gpio_inputs |= (REG_READ(GPIO_IN_REG) >> GPIO_PIN_12) & 0x3F;
        REG_WRITE(GPIO_OUT_W1TC_REG, (1 << GPIO_CLOCK));
        gpio_inputs |= ((REG_READ(GPIO_IN_REG) >> GPIO_PIN_32) & 0x3F) << 6;

        if (trigger)
        {
            for (; k < NUM_CYCLES; k++)
            {
                REG_WRITE(GPIO_OUT_W1TS_REG, (1 << GPIO_CLOCK));
                data_array[k] = REG_READ(GPIO_IN_REG) & ((1ULL << NUM_GPIO_PINS) - 1);

                //Block bellow is noly for debugging
                printf("GPIO Pin 12: %d\n", gpio_get_level(GPIO_PIN_12));
                printf("GPIO Pin 13: %d\n", gpio_get_level(GPIO_PIN_13));
                printf("GPIO Pin 2: %d\n", gpio_get_level(GPIO_PIN_2));
                printf("GPIO Pin 4: %d\n", gpio_get_level(GPIO_PIN_4));
                printf("GPIO Pin 16: %d\n", gpio_get_level(GPIO_PIN_16));
                printf("GPIO Pin 17: %d\n", gpio_get_level(GPIO_PIN_17));
                printf("GPIO Pin 32: %d\n", gpio_get_level(GPIO_PIN_32));
                printf("GPIO Pin 33: %d\n", gpio_get_level(GPIO_PIN_33));
                printf("GPIO Pin 34: %d\n", gpio_get_level(GPIO_PIN_34));
                printf("GPIO Pin 35: %d\n", gpio_get_level(GPIO_PIN_35));
                printf("GPIO Pin 36: %d\n", gpio_get_level(GPIO_PIN_36));
                printf("GPIO Pin 39: %d\n", gpio_get_level(GPIO_PIN_39));
                printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");

                REG_WRITE(GPIO_OUT_W1TC_REG, (1 << GPIO_CLOCK));
            }

            k = 0;

            for (; k < NUM_CYCLES; k++)
            {
                printf("Cycle %d: %d\n", k + 1, data_array[k]);
            }
            printf("-----------------------------------------------------------\n");
            memset(data_array, 0, sizeof(data_array));
            k = 0;
            trigger = false;
        }
    }
}
logs:
Cycle 1: 2699
Cycle 2: 2699
Cycle 3: 2699
Cycle 4: 2699
Cycle 5: 2699
Cycle 6: 2699
Cycle 7: 2699
Cycle 8: 2699
Cycle 9: 2699
Cycle 10: 2699
Cycle 11: 2699
Cycle 12: 2699
Cycle 13: 2699
Cycle 14: 2699
Cycle 15: 2699
Cycle 16: 2699
Cycle 17: 2699
Cycle 18: 2699
Cycle 19: 2699
Cycle 20: 2699
Cycle 21: 2699
Cycle 22: 2699
Cycle 23: 2699
Cycle 24: 2699
Cycle 25: 2699
Cycle 26: 2699
Cycle 27: 2699
Cycle 28: 2699
Cycle 29: 2699
Cycle 30: 2699
Cycle 31: 2699
Cycle 32: 2699
Cycle 33: 2699
Cycle 34: 2699
Cycle 35: 2699
Cycle 36: 2699
Cycle 37: 2699
Cycle 38: 2699
Cycle 39: 2699
Cycle 40: 2699
Cycle 41: 2699
Cycle 42: 2699
Cycle 43: 2699
Cycle 44: 2699
Cycle 45: 2699
Cycle 46: 2699
Cycle 47: 2699
Cycle 48: 2699
Cycle 49: 2699
Cycle 50: 2699
Cycle 51: 2699
Cycle 52: 2699
Cycle 53: 2699
Cycle 54: 2699
Cycle 55: 2699
Cycle 56: 2699
Cycle 57: 2699
Cycle 58: 2699
Cycle 59: 2699
Cycle 60: 2699
Cycle 61: 2699
Cycle 62: 2699
Cycle 63: 2699
Cycle 64: 2699
Cycle 65: 2699
Cycle 66: 2699
Cycle 67: 2699
Cycle 68: 2699
Cycle 69: 2699
Cycle 70: 2699
Cycle 71: 2699
Cycle 72: 2699
Cycle 73: 2699
Cycle 74: 2699
Cycle 75: 2699
Cycle 76: 2699
Cycle 77: 2699
Cycle 78: 2699
Cycle 79: 2699
Cycle 80: 2699
Cycle 81: 2699
Cycle 82: 2699
Cycle 83: 2699
Cycle 84: 2699
Cycle 85: 2699
Cycle 86: 2699
Cycle 87: 2699
Cycle 88: 2699
Cycle 89: 2699
Cycle 90: 2699
Cycle 91: 2699
Cycle 92: 2699
Cycle 93: 2699
Cycle 94: 2699
Cycle 95: 2699
Cycle 96: 2699
Cycle 97: 2699
Cycle 98: 2699
Cycle 99: 2699
Cycle 100: 2699
-----------------------------------------------------------
Attachments
sch.jpg
sch.jpg (236.61 KiB) Viewed 62484 times

User avatar
ok-home
Posts: 78
Joined: Sun May 02, 2021 7:23 pm
Location: Russia Novosibirsk
Contact:

Re: Unpredictable GPIO inputs behavior

Postby ok-home » Thu Dec 07, 2023 1:59 pm

hi
Have you actually looked at the datasheet ?
Attachments
gpio.JPG
gpio.JPG (47.4 KiB) Viewed 62452 times

Vilius
Posts: 26
Joined: Mon Nov 13, 2023 9:22 am

Re: Unpredictable GPIO inputs behavior

Postby Vilius » Thu Dec 07, 2023 9:14 pm

Hi,

yeah I saw that part. Please excuse and correct me, no bad intentions at all, just lack of practice, but to my understanding x at the inputs indicates that I can use that pin. I mean I am not passing to the reserved bits of the IN1 register, so is there any problem?

Or did you mean that I have to read from both registers? (IN and IN1?)

MicroController
Posts: 1706
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Unpredictable GPIO inputs behavior

Postby MicroController » Thu Dec 07, 2023 9:58 pm

Yup.

Code: Select all

data_array[k] = REG_READ(GPIO_IN_REG) & ((1ULL << NUM_GPIO_PINS) - 1);
Reads & returns the value/state of GPIO_PIN_11...GPIO_PIN_0. Not what you want. And for GPIO_PIN_32 and up, you have to read GPIO_IN1_REG/GPIO_IN_DATA_NEXT.

Vilius
Posts: 26
Joined: Mon Nov 13, 2023 9:22 am

Re: Unpredictable GPIO inputs behavior

Postby Vilius » Mon Dec 11, 2023 11:50 am

Ok, I partially solved that problem, my code now:

Code: Select all

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "soc/soc.h"
#include "soc/gpio_struct.h"
#include "soc/gpio_reg.h"
#include "esp32/rom/ets_sys.h"
#include "soc/rtc.h"

#define INTERRUPT_INPUT 15
#define GPIO_CLOCK 14 
#define NUM_GPIO_PINS 12
#define NUM_CYCLES 80

#define GPIO_PIN_12 12   //LSB
#define GPIO_PIN_13 13
#define GPIO_PIN_2 2
#define GPIO_PIN_4 4
#define GPIO_PIN_16 16
#define GPIO_PIN_17 17
#define GPIO_PIN_32 32
#define GPIO_PIN_33 33
#define GPIO_PIN_34 34
#define GPIO_PIN_35 35
#define GPIO_PIN_36 36
#define GPIO_PIN_39 39   //MSB

const uint32_t gpio_pins[NUM_GPIO_PINS] = {
    12, 13, 2, 4, 16, 17, 32, 33, 34, 35, 36, 39
};

static const gpio_num_t GPIO_PINS[NUM_GPIO_PINS] = {
    GPIO_PIN_12, GPIO_PIN_13, GPIO_PIN_2, GPIO_PIN_4,
    GPIO_PIN_16, GPIO_PIN_17, GPIO_PIN_32, GPIO_PIN_33,
    GPIO_PIN_34, GPIO_PIN_35, GPIO_PIN_36, GPIO_PIN_39
};

bool trigger = false;
uint32_t data_array[NUM_CYCLES] = {0};

static void IRAM_ATTR gpio_interrupt_handler(void *args)
{
    trigger = true;
}

void disableWatchdog()
{
    WRITE_PERI_REG(RTC_CNTL_WDTCONFIG0_REG, 0);
    WRITE_PERI_REG(RTC_CNTL_WDTCONFIG1_REG, 0);
}

void app_main()
{
    vTaskDelay(200 / portTICK_PERIOD_MS);
    esp_rom_gpio_pad_select_gpio(INTERRUPT_INPUT);
    gpio_set_direction(INTERRUPT_INPUT, GPIO_MODE_INPUT);
    gpio_pulldown_en(INTERRUPT_INPUT);
    gpio_pullup_dis(INTERRUPT_INPUT);
    gpio_set_intr_type(INTERRUPT_INPUT, GPIO_INTR_NEGEDGE);

    gpio_install_isr_service(0);
    gpio_isr_handler_add(INTERRUPT_INPUT, gpio_interrupt_handler, (void *)INTERRUPT_INPUT);

    gpio_config_t io_conf_output = {
        .pin_bit_mask = (1ULL << GPIO_CLOCK),
        .mode = GPIO_MODE_OUTPUT,
    };
    gpio_config(&io_conf_output);

    gpio_config_t io_conf;
    for (int i = 0; i < NUM_GPIO_PINS; ++i)
    {
        io_conf = (gpio_config_t){
            .pin_bit_mask = (1ULL << GPIO_PINS[i]),
            .mode = GPIO_MODE_INPUT,
            .intr_type = GPIO_INTR_DISABLE,
            .pull_up_en = GPIO_PULLUP_DISABLE,
            .pull_down_en = GPIO_PULLDOWN_ENABLE,  // Enable pulldown resistors
        };
        gpio_config(&io_conf);
    }


    uint32_t reg_in = 0;
    uint32_t reg_in1 = 0;
    disableWatchdog();
    int k = 0;

    uint32_t pin12_mask = 1U << 12;
    uint32_t pin13_mask = 1U << 13;
    uint32_t pin2_mask = 1U << 2;
    uint32_t pin4_mask = 1U << 4;
    uint32_t pin16_mask = 1U << 16;
    uint32_t pin17_mask = 1U << 17;
    uint32_t pin32_mask = 1U << (32 - 32);
    uint32_t pin33_mask = 1U << (33 - 32);
    uint32_t pin34_mask = 1U << (34 - 32);
    uint32_t pin35_mask = 1U << (35 - 32);
    uint32_t pin36_mask = 1U << (36 - 32);
    uint32_t pin39_mask = 1U << (39 - 32);

    while (1)
    {
        
    
            REG_WRITE(GPIO_OUT_W1TS_REG, (1 << GPIO_CLOCK));

            reg_in = REG_READ(GPIO_IN_REG);
            reg_in1 = REG_READ(GPIO_IN1_REG);
            data_array[k] =((reg_in >> 12) & 0x01) | ((reg_in >> 13) & 0x01) << 1 | ((reg_in >> 2) & 0x01) << 2 | ((reg_in >> 4) & 0x01) << 3 | (((reg_in >> 16) & 0x01) ^ 1) << 4 | ((reg_in >> 17) & 0x01) << 5 | ((reg_in1 >> (32 - 32)) & 0x01) << 6 | ((reg_in1 >> (33 - 32)) & 0x01) << 7 | ((reg_in1 >> (34 - 32)) & 0x01) << 8 | ((reg_in1 >> (35 - 32)) & 0x01) << 9 | ((reg_in1 >> (36 - 32)) & 0x01) << 10 | ((reg_in1 >> (39 - 32)) & 0x01);

            REG_WRITE(GPIO_OUT_W1TC_REG, (1 << GPIO_CLOCK));
            
            k = (k + 1) % NUM_CYCLES;

        if (trigger)
        {
            
            for (int i=0; i < NUM_CYCLES; i++)
            {
                printf("Cycle %d: %ld", i + 1, data_array[i]);
                printf("\n");
            /* For printing data in binary
               printf("Cycle %d: ", k + 1);
               for (int i = 31; i >= 0; --i) {
               printf("%ld", (data_array[k] >> i) & 1);
               if (i % 4 == 0 && i > 0) {
                    printf(" ");
                }
                }
                printf("\n");
            */
            }

           printf("-----------------------------------------------------------\n");
           trigger = false;
        }
    }
}
I fixed the register part and implemented a circular buffer, since I am always sampling voltage pulses and the interrupt pulse only tells me when my data is valuable (has some new information-pulse stored in it.) My ADC is working in 0-4V isolated supply so for 12 bits, value of 1 represents 1 mV etc. For testing, the generated analog pulses are identical.

Here are some of the circular buffer readings when pulses are present:
-----------------------------------------------------------
Cycle 1: 201
Cycle 2: 205
Cycle 3: 205
Cycle 4: 202
Cycle 5: 207
Cycle 6: 201
Cycle 7: 207
Cycle 8: 203
Cycle 9: 201
Cycle 10: 203
Cycle 11: 197
Cycle 12: 205
Cycle 13: 206
Cycle 14: 205
Cycle 15: 201
Cycle 16: 206
Cycle 17: 195
Cycle 18: 201
Cycle 19: 204
Cycle 20: 202
Cycle 21: 202
Cycle 22: 202
Cycle 23: 201
Cycle 24: 200
Cycle 25: 207
Cycle 26: 201
Cycle 27: 204
Cycle 28: 193
Cycle 29: 197
Cycle 30: 196
Cycle 31: 202
Cycle 32: 205
Cycle 33: 202
Cycle 34: 203
Cycle 35: 197
Cycle 36: 196
Cycle 37: 203
Cycle 38: 204
Cycle 39: 202
Cycle 40: 204
Cycle 41: 388
Cycle 42: 1094
Cycle 43: 1998
Cycle 44: 655
Cycle 45: 781
Cycle 46: 202
Cycle 47: 201
Cycle 48: 197
Cycle 49: 201
Cycle 50: 206
Cycle 51: 202
Cycle 52: 197
Cycle 53: 202
Cycle 54: 198
Cycle 55: 202
Cycle 56: 203
Cycle 57: 207
Cycle 58: 201
Cycle 59: 204
Cycle 60: 195
Cycle 61: 200
Cycle 62: 192
Cycle 63: 203
Cycle 64: 202
Cycle 65: 201
Cycle 66: 200
Cycle 67: 201
Cycle 68: 203
Cycle 69: 205
Cycle 70: 202
Cycle 71: 203
Cycle 72: 200
Cycle 73: 194
Cycle 74: 203
Cycle 75: 192
Cycle 76: 202
Cycle 77: 199
Cycle 78: 202
Cycle 79: 197
Cycle 80: 202
-----------------------------------------------------------
Cycle 1: 193
Cycle 2: 199
Cycle 3: 198
Cycle 4: 198
Cycle 5: 201
Cycle 6: 203
Cycle 7: 207
Cycle 8: 202
Cycle 9: 202
Cycle 10: 206
Cycle 11: 198
Cycle 12: 324
Cycle 13: 971
Cycle 14: 1928
Cycle 15: 579
Cycle 16: 771
Cycle 17: 202
Cycle 18: 195
Cycle 19: 201
Cycle 20: 205
Cycle 21: 201
Cycle 22: 196
Cycle 23: 201
Cycle 24: 206
Cycle 25: 200
Cycle 26: 203
Cycle 27: 192
Cycle 28: 201
Cycle 29: 197
Cycle 30: 204
Cycle 31: 204
Cycle 32: 201
Cycle 33: 202
Cycle 34: 200
Cycle 35: 195
Cycle 36: 203
Cycle 37: 205
Cycle 38: 204
Cycle 39: 197
Cycle 40: 200
Cycle 41: 199
Cycle 42: 192
Cycle 43: 204
Cycle 44: 198
Cycle 45: 198
Cycle 46: 205
Cycle 47: 202
Cycle 48: 196
Cycle 49: 202
Cycle 50: 205
Cycle 51: 200
Cycle 52: 200
Cycle 53: 197
Cycle 54: 204
Cycle 55: 207
Cycle 56: 192
Cycle 57: 195
Cycle 58: 200
Cycle 59: 200
Cycle 60: 198
Cycle 61: 202
Cycle 62: 192
Cycle 63: 205
Cycle 64: 197
Cycle 65: 199
Cycle 66: 198
Cycle 67: 204
Cycle 68: 205
Cycle 69: 201
Cycle 70: 199
Cycle 71: 204
Cycle 72: 200
Cycle 73: 198
Cycle 74: 206
Cycle 75: 192
Cycle 76: 205
Cycle 77: 200
Cycle 78: 195
Cycle 79: 196
Cycle 80: 204
-----------------------------------------------------------
Cycle 1: 206
Cycle 2: 206
Cycle 3: 205
Cycle 4: 202
Cycle 5: 204
Cycle 6: 201
Cycle 7: 204
Cycle 8: 200
Cycle 9: 201
Cycle 10: 205
Cycle 11: 205
Cycle 12: 197
Cycle 13: 202
Cycle 14: 202
Cycle 15: 205
Cycle 16: 204
Cycle 17: 199
Cycle 18: 199
Cycle 19: 193
Cycle 20: 200
Cycle 21: 201
Cycle 22: 200
Cycle 23: 206
Cycle 24: 204
Cycle 25: 205
Cycle 26: 200
Cycle 27: 201
Cycle 28: 201
Cycle 29: 202
Cycle 30: 201
Cycle 31: 204
Cycle 32: 204
Cycle 33: 204
Cycle 34: 200
Cycle 35: 199
Cycle 36: 200
Cycle 37: 193
Cycle 38: 202
Cycle 39: 198
Cycle 40: 201
Cycle 41: 203
Cycle 42: 202
Cycle 43: 205
Cycle 44: 201
Cycle 45: 207
Cycle 46: 203
Cycle 47: 205
Cycle 48: 201
Cycle 49: 207
Cycle 50: 206
Cycle 51: 205
Cycle 52: 200
Cycle 53: 202
Cycle 54: 201
Cycle 55: 203
Cycle 56: 205
Cycle 57: 202
Cycle 58: 203
Cycle 59: 198
Cycle 60: 200
Cycle 61: 205
Cycle 62: 204
Cycle 63: 205
Cycle 64: 207
Cycle 65: 580
Cycle 66: 1414
Cycle 67: 259
Cycle 68: 773
Cycle 69: 781
Cycle 70: 202
Cycle 71: 199
Cycle 72: 200
Cycle 73: 204
Cycle 74: 203
Cycle 75: 203
Cycle 76: 202
Cycle 77: 205
Cycle 78: 203
Cycle 79: 201
Cycle 80: 198
-----------------------------------------------------------

Oscilloscope shows that I get around 10 sample for every pulse, because I toggle the ADC clock GPIO on ESP32 every read cycle. Logs indicate that I do get some kind of voltage spikes, but it is not nearly evenly distributed over 10 samples. I spent quite some time on this and I verified that my interrupt pulses are ok and I am indeed reading the ADC output values this time. Maybe its not entirely ESP32 problem, but have you got any observations, why my circular data buffer looks so messy? Is it related to insufficient timing or something similar? (Check the screenshot bellow).
Attachments
Capture.PNG
Capture.PNG (85.37 KiB) Viewed 62015 times

Who is online

Users browsing this forum: No registered users and 75 guests