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

GPIOTE Event In Handler Not Triggering

Hello good people at Nordic. Happy new year!

I am attempting a simple extension of the GPIOTE example in the SDK. I want to measure the time duration of the generated pulse from the example.

In my setup, I have configured two GPIOTE input channels, two PPI channels and a timer to accomplish this.

On a breadboard, I have attached GPIO Pin 0.5 to GPIO Pins 0.11 and 0.21 through a 3k resistor.

I am very close to making it work, however I have a problem where I can't trigger the GPIOTE Low to High channel. I have tried adding debug statements in the handler as well as trying swapping the GPIOTE and PPI channels to see if that would cause any activity on that GPIOTE channel, but saw nothing.

When I run the program as is, the timer compare value is the total period duration, not the high period. 6 milliseconds in this case, indicating that the timer is only being reset in the hitolo_handler and not by the PPI lotohi channel like it should.

I know that the High to Low GPIOTE channel on pin 11 works, as the variables and debugging prints I've added in the handler are activated.

I even got out the GNU Debugger and probed the PPI and GPIOTE registers, but saw no indication of the registers being misconfigured. I can provide the data of the probing if there appears nothing wrong with the code.

#include <stdio.h>
#include <stdint.h>
#include "nrf.h"
#include "boards.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "nrf_drv_twi.h"

#include "nrf_delay.h"

//UART Logging
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

//timer stuff
#include "nrf_drv_timer.h"

//gpiote stuff
#include "nrf_drv_gpiote.h"
#include "nrf_gpio.h"
#include "nrf_gpiote.h"

//ppi stuff
#include "nrf_drv_ppi.h"

#define GPIO_OUTPUT_PIN_NUMBER  5
#define GPIO_LOTOHI_INPUT_PIN_NUMBER   21  
#define GPIO_HITOLO_INPUT_PIN_NUMBER   11
#ifndef GPIO_OUTPUT_PIN_NUMBER
    #error "Please indicate output pin"
#endif

#ifndef GPIO_OUTPUT_PIN_NUMBER
    #error "Please indicate output pin"
#endif

uint32_t gpiote_lotohi_event_addr;
uint32_t gpiote_hitolo_event_addr;
uint32_t timer_start_task_addr;
uint32_t timer_stop_task_addr;
uint32_t timer_capture_task_addr;
uint32_t timer_clear_task_addr;

uint32_t timerVal;

ret_code_t err_code;

static nrf_drv_timer_t timer = NRF_DRV_TIMER_INSTANCE(0);

// create timer for measuring input pulse duration
static nrf_drv_timer_t pulse_meas = NRF_DRV_TIMER_INSTANCE(1);

// create second ppi channel for hi to lo input
nrf_ppi_channel_t ppi_channel_lotohi;
//create third ppi channel for lo to hi input
nrf_ppi_channel_t ppi_channel_hitolo;

//create third gpiote in config for catching hi to lo transitions
nrf_drv_gpiote_in_config_t config_hitolo = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);

//tracking inputs
nrf_drv_gpiote_in_config_t config_lotohi = GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);//second arg is high accuracy - i.e. IN_EVENT[i]


void hitolo_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action){

    timerVal = nrfx_timer_capture_get(&pulse_meas, 0); // store timer compare val for later use

    nrfx_timer_clear(&pulse_meas); 
}

void lotohi_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action){

    NRF_LOG_INFO(";"); // not seeing in this in output

}

void timer_dummy_handler(nrf_timer_event_t event_type, void * p_context){

    NRF_LOG_INFO(",");
}

static void gpiote_ppi_input_setup(){

    uint32_t compare_evt_addr;
    uint32_t gpiote_task_addr;

    nrf_ppi_channel_t ppi_channel;

    // 5. gpiote config
    nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);//second arg is init hi or lo
    
    // 5 1/2. gpiote out init
    err_code = nrf_drv_gpiote_out_init(GPIO_OUTPUT_PIN_NUMBER, &config);
    //NRF_LOG_INFO("err=%d", err_code);

    //gpiote in init

    err_code = nrf_drv_gpiote_in_init(GPIO_HITOLO_INPUT_PIN_NUMBER, &config_lotohi, hitolo_handler);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_gpiote_in_init(GPIO_LOTOHI_INPUT_PIN_NUMBER, &config_hitolo, hitolo_handler);
    APP_ERROR_CHECK(err_code);

    uint32_t tick = nrfx_timer_ms_to_ticks(&timer, 3); //configure timer compare value to x milliseconds
    // 6. timer extended compare
    nrf_drv_timer_extended_compare(&timer, (nrf_timer_cc_channel_t)0, tick, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);

    // 7. ppi alloc
   //allocate for first channel - pulse gen channel
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel);
    APP_ERROR_CHECK(err_code);

    //allocate for second channel
    err_code = nrfx_ppi_channel_alloc(&ppi_channel_lotohi);
    APP_ERROR_CHECK(err_code);

    //allocate for third channel
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel_hitolo);
    APP_ERROR_CHECK(err_code);

    // 8. address get

    // for pulse generation
    compare_evt_addr = nrf_drv_timer_event_address_get(&timer, NRF_TIMER_EVENT_COMPARE0);
    gpiote_task_addr = nrf_drv_gpiote_out_task_addr_get(GPIO_OUTPUT_PIN_NUMBER);

    //get gpiote LOTOHI in event address
    //get timer start task address
    //get timer capture task address

    gpiote_lotohi_event_addr = nrf_drv_gpiote_in_event_addr_get(GPIO_LOTOHI_INPUT_PIN_NUMBER);
    timer_start_task_addr = nrf_drv_timer_task_address_get(&pulse_meas, NRF_TIMER_TASK_START);
    timer_clear_task_addr = nrf_drv_timer_task_address_get(&pulse_meas, NRF_TIMER_TASK_CLEAR);

    //get gpiote hitolo in event address
    //get timer stop task address
    //get timer clear task address
    gpiote_hitolo_event_addr = nrf_drv_gpiote_in_event_addr_get(GPIO_HITOLO_INPUT_PIN_NUMBER);
    timer_stop_task_addr = nrf_drv_timer_task_address_get(&pulse_meas, NRF_TIMER_TASK_STOP);
    timer_capture_task_addr = nrf_drv_timer_task_address_get(&pulse_meas, NRF_TIMER_TASK_CAPTURE0);

    // 9. ppi channel assigns

    // assign first ppi channel 
    err_code = nrf_drv_ppi_channel_assign(ppi_channel, compare_evt_addr, gpiote_task_addr);
    APP_ERROR_CHECK(err_code);

    //assign second ppi channel per gpiote event and timer task
    err_code = nrfx_ppi_channel_assign(ppi_channel_lotohi, gpiote_lotohi_event_addr, timer_start_task_addr);
    APP_ERROR_CHECK(err_code);
    err_code = nrfx_ppi_channel_fork_assign(ppi_channel_lotohi,timer_clear_task_addr); // not seeing this occur
    APP_ERROR_CHECK(err_code);

    //assign third ppi channel per gpiote event and timer task
    err_code = nrf_drv_ppi_channel_assign(ppi_channel_hitolo, gpiote_hitolo_event_addr, timer_capture_task_addr);
    APP_ERROR_CHECK(err_code);

    // 10. ppi channel enable
    //enables pulse gen
    err_code = nrf_drv_ppi_channel_enable(ppi_channel);
    APP_ERROR_CHECK(err_code);

    //enable lotohi channel
    err_code = nrfx_ppi_channel_enable(ppi_channel_lotohi);
    APP_ERROR_CHECK(err_code);

    //enable hitolo channel
    err_code = nrf_drv_ppi_channel_enable(ppi_channel_hitolo);
    APP_ERROR_CHECK(err_code);

    // 11. gpiote task/event enable
    //enable output task for pulse gen
    nrf_drv_gpiote_out_task_enable(GPIO_OUTPUT_PIN_NUMBER);

    //enable gpiote event

    nrf_drv_gpiote_in_event_enable(GPIO_HITOLO_INPUT_PIN_NUMBER, true); //second arg is int_enable
    nrfx_gpiote_in_event_enable(GPIO_LOTOHI_INPUT_PIN_NUMBER, true); //second arg is int_en

}

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("\r\n Starting Example.");
    NRF_LOG_FLUSH();

    // 1. ppi init
    nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    // 2. gpiote init
    err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);

    // 1. timer config - pulse gen and measure timers configured the same 
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.bit_width = 3;
    // 2. timer init
    err_code = nrf_drv_timer_init(&timer, &timer_cfg, timer_dummy_handler);
    APP_ERROR_CHECK(err_code);

    //timer config for measuring input pulse
    err_code = nrf_drv_timer_init(&pulse_meas, &timer_cfg, timer_dummy_handler);
    APP_ERROR_CHECK(err_code);

    gpiote_ppi_input_setup();

    // 5. Enable timer
    nrf_drv_timer_enable(&timer);
    nrf_drv_timer_enable(&pulse_meas);
    //nrf_drv_timer_resume(&pulse_meas);

    while(true){
	//print out timer values to serial port
	NRF_LOG_INFO("timerVal=%d",timerVal);
	NRF_LOG_FLUSH();

	timerVal=0; //just checking if value is being updated
	nrf_delay_ms(2000);

    }

}

Best wishes for 2021!

Related