This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Pin interrupt triggered without transitioning from HI-to-LOW

I am using an ADC where the SPI MISO pin also acts as a data ready pin when it transitions from Hi-to-Low as detailed in the link below. I am able to configure this and it works as intended when I configure the pin to be high accuracy  NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true).

https://devzone.nordicsemi.com/f/nordic-q-a/25047/are-spi-interrupt-disabled-in-gpiote-handler

 

my configurations:

nrfx_gpiote_in_config_t adc_drdy_pin_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
err_code = nrf_drv_gpiote_in_init(SPI_MISO_PIN, &adc_drdy_pin_config, adc_drdy_interrupt_handler);
APP_ERROR_CHECK(err_code);
nrfx_gpiote_in_event_enable(SPI_MISO_PIN, false);

the adc_drdy_interrupt_handler gets triggered as soon as the nrfx_gpiote_in_event_enable(SPI_MISO_PIN, false) function is executed. note that I am not even enabling the interrupt event. how can this be happening?

the pin starts low but the handler should NOT be getting triggered since the pin did NOT transition from high to low. if i run the app with NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true), everything functions as it should. I am trying to lower my power consumption and I am using SDK 15.0.0 and S132. I have been at this problem for days and any help would be greatly appreciated.

  • Wael said:
    also, how can I make sure they are on different GPIOTE_IN channels?

     For the PORT event (high_accuracy = false), there's no dedicated channel. All pins, configured with SENSE, will generate a EVENTS_PORT.

  • Hi 

    I did and it works. but I do not see any current difference between the high and low accuracy. you can see from the plot below the cpu never goes to sleep. the interrupt handler gets triggered very 1.3 ms. the average current for bothe low and high accuracy look the same.

      

    this is what I do in my init_gpio function
    
        nrfx_gpiote_in_config_t adc_drdy_pin_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(false);
        NRFX_IRQ_DISABLE(GPIOTE_IRQn); // disable the GPIOTE IRQs
        //nrfx_gpiote_in_uninit(SPI_MISO_PIN); // uninit this pin, else we get error
        adc_drdy_pin_config.pull = NRF_GPIO_PIN_PULLUP;
        err_code = nrf_drv_gpiote_in_init(SPI_MISO_PIN, &adc_drdy_pin_config, adc_drdy_interrupt_handler);
        APP_ERROR_CHECK(err_code);
        nrfx_gpiote_in_event_enable(SPI_MISO_PIN, false);
        nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT); // clear the spontanious interrupt that was triggered from calling nrfx_gpiote_in_event_enable()
        NRFX_IRQ_ENABLE(GPIOTE_IRQn); // enable the GPIOTE IRQs	
        
        
    this is my interrupt handler
    
    static void adc_drdy_interrupt_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
        uint32_t       sensor_data = 0;
        uint32_t       dStatus = 0;
        uint32_t       dCRC = 0;
        uint32_t       cCRC = 0;
        ret_code_t     err_code = 0;
      
        NRF_LOG_INFO("Interrupt Counter = %d\n", app_timer_cnt_get());
        nrfx_gpiote_in_event_enable(SPI_MISO_PIN, false);
        nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT); // clear the spontanious interrupt that was triggered from calling nrfx_gpiote_in_event_enable()      
        CRITICAL_REGION_ENTER();
        sensor_data = dataRead(&dStatus, &dCRC);
        cCRC = compute_adc_crc8(sensor_data, dStatus);
      
        if(cCRC != dCRC)
        {
            NRF_LOG_INFO("Received CRC does NOT match calculated CRC! S%d, ADC DATA = 0x%X, recCRC = 0x%X, cCRC = 0x%X, Status = 0x%X", m_adc_sensor_number, sensor_data, dCRC, cCRC, dStatus);
            return;
        }
        
        CRITICAL_REGION_EXIT();  
        
        NRF_LOG_INFO("S%d ADC DATA = 0x%X\n", m_adc_sensor_number, sensor_data);
        switch(m_adc_sensor_number)
        {
          case 1:
            registers[INPMUX_ADDR_MASK]= ADS_P_AIN2 | ADS_N_AIN3;     // S2  
            regWrite(INPMUX_ADDR_MASK, registers[INPMUX_ADDR_MASK]);
          
            read_strain_gauge_data_result[0] = (uint8_t)((sensor_data >> 16) & 0xFF);
            read_strain_gauge_data_result[1] = (uint8_t)((sensor_data >> 8) & 0xFF);
            read_strain_gauge_data_result[2] = (uint8_t)(sensor_data & 0xFF);      
            m_adc_sensor_number++;
            break;
          case 2:
            registers[INPMUX_ADDR_MASK]= ADS_P_AIN4 | ADS_N_AIN5;     // S3
            regWrite(INPMUX_ADDR_MASK, registers[INPMUX_ADDR_MASK]);
          
            read_strain_gauge_data_result[3] = (uint8_t)((sensor_data >> 16) & 0xFF);
            read_strain_gauge_data_result[4] = (uint8_t)((sensor_data >> 8) & 0xFF);
            read_strain_gauge_data_result[5] = (uint8_t)(sensor_data & 0xFF);
            m_adc_sensor_number++;
            break;
          case 3:
            registers[INPMUX_ADDR_MASK]= ADS_P_AIN6 | ADS_N_AIN7;   // S4
            regWrite(INPMUX_ADDR_MASK, registers[INPMUX_ADDR_MASK]);
          
            read_strain_gauge_data_result[6] = (uint8_t)((sensor_data >> 16) & 0xFF);
            read_strain_gauge_data_result[7] = (uint8_t)((sensor_data >> 8) & 0xFF);
            read_strain_gauge_data_result[8] = (uint8_t)(sensor_data & 0xFF);
            m_adc_sensor_number++;
            break;
          case 4:
            registers[INPMUX_ADDR_MASK]= ADS_P_AIN8 | ADS_N_AIN9;   // S5
            regWrite(INPMUX_ADDR_MASK, registers[INPMUX_ADDR_MASK]);
          
            read_strain_gauge_data_result[9] = (uint8_t)((sensor_data >> 16) & 0xFF);
            read_strain_gauge_data_result[10] = (uint8_t)((sensor_data >> 8) & 0xFF);
            read_strain_gauge_data_result[11] = (uint8_t)(sensor_data & 0xFF);
            m_adc_sensor_number++;
            break;
          case 5:
            registers[INPMUX_ADDR_MASK]= ADS_P_AIN10 | ADS_N_AIN11; // S6
            regWrite(INPMUX_ADDR_MASK, registers[INPMUX_ADDR_MASK]);
          
            read_strain_gauge_data_result[12] = (uint8_t)((sensor_data >> 16) & 0xFF);
            read_strain_gauge_data_result[13] = (uint8_t)((sensor_data >> 8) & 0xFF);
            read_strain_gauge_data_result[14] = (uint8_t)(sensor_data & 0xFF);
            m_adc_sensor_number++;
            break;
          case 6:
            registers[INPMUX_ADDR_MASK]= ADS_P_AIN0 | ADS_N_AIN1; // S1
            regWrite(INPMUX_ADDR_MASK, registers[INPMUX_ADDR_MASK]);
          
            read_strain_gauge_data_result[15] = (uint8_t)((sensor_data >> 16) & 0xFF);
            read_strain_gauge_data_result[16] = (uint8_t)((sensor_data >> 8) & 0xFF);
            read_strain_gauge_data_result[17] = (uint8_t)(sensor_data & 0xFF);
            m_adc_sensor_number = 1;
            break;
          default:
            NRF_LOG_ERROR("Unknown Sensor number! Sensor Number = %d\n.", device_operating_second_count);
            break;
        } 
        nrfx_gpiote_in_event_enable(SPI_MISO_PIN, true);
        nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT); // clear the spontanious interrupt that was triggered from calling nrfx_gpiote_in_event_enable()
        
    }

  • You are doing quite a lot of processing and log printing in this handler, so if you're waking up every 1.3 ms, the log printing alone will account for quite some time.

    Try toggling a pin inside the handler, and for debugging purposes; keep the function small, and see how often it toggles using a logic analyzer / oscilloscope.

Related