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

nRF52 DK improper GPIOTE --> PPI configuration (no interrupts being raised on input toggle)

#define PIN_IN 1
struct queue* q;

void start_timer(void)
{		
    NRF_LOG_INFO("initializing NRF_TIMER1...");
    NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;              // Set the timer in Counter Mode
    NRF_TIMER1->TASKS_CLEAR = 1;                             // clear the task first to be usable for later
	NRF_TIMER1->PRESCALER = 4;                              //us granularity
	NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_32Bit;		   //Set counter to 32 bit resolution
		
	NRF_TIMER1->TASKS_START = 1;               // Start TIMER1
}

static void gpio_init(void)
{
        sd_nvic_DisableIRQ(GPIOTE_IRQn);
		sd_nvic_ClearPendingIRQ(GPIOTE_IRQn);
		NRF_LOG_INFO("initializing gpio...");
		
		NRF_GPIOTE->INTENSET = (GPIOTE_INTENSET_IN1_Disabled << GPIOTE_INTENSET_IN1_Pos);
		
		nrf_gpio_cfg_input(PIN_IN, NRF_GPIO_PIN_PULLDOWN);
	
		NRF_GPIOTE->CONFIG[1] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos)
			| (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos)
			| (PIN_IN << GPIOTE_CONFIG_PSEL_Pos); // IN event
    
		NRF_GPIOTE->INTENSET = (GPIOTE_INTENSET_IN1_Enabled << GPIOTE_INTENSET_IN1_Pos);
		
		//sd_nvic_SetPriority(GPIOTE_IRQn, 1);
		sd_nvic_EnableIRQ(GPIOTE_IRQn);
}


// ppi linkage
static void ppi_init(void)
{
	NRF_LOG_INFO("initializing ppi linkage...");
	// disable PPI channel 1
	NRF_PPI->CHEN = (PPI_CHEN_CH1_Disabled << PPI_CHEN_CH1_Pos);
	
	//on every GPIO polarity toggle encounter/interupts
	NRF_PPI->CH[1].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[1];
	// put time in us into CC[1] register
	NRF_PPI->CH[1].TEP = (uint32_t)&NRF_TIMER1->TASKS_CAPTURE[1];
    // Enable PPI channel 1
    NRF_PPI->CHEN = (PPI_CHEN_CH1_Enabled << PPI_CHEN_CH1_Pos);
}

// I assume this is called every time there is an interupt (polarity toggle on input pin)
void GPIOTE_IRQHandler(void)
{
    NRF_LOG_INFO("in GPIOTE_IRQHandler...");
	if(NRF_GPIOTE->EVENTS_IN[1] != 0)
    {
        NRF_GPIOTE->EVENTS_IN[1] = 0;
		
		//NRF_LOG_INFO("GPIOTE handler: %i", NRF_TIMER1->CC[1]);
		//NRF_LOG_FLUSH();
		
		//restart timer		
		NRF_TIMER1->TASKS_CLEAR = 1;
		
		// queue microsecond data
		enQueue(q, NRF_TIMER1->CC[1]);
				
    }
}

int main{
        q = (struct queue*)malloc(sizeof(struct queue)); 
		q->stack1 = NULL; 
		q->stack2 = NULL;
		q->size = 0;
		
		start_timer();
		
		NRF_LOG_INFO("waiting to initialize GPIO IRQ...")
		NRF_LOG_FLUSH();
		
		nrf_delay_ms(1000);
		
		gpio_init();
		
		NRF_LOG_INFO("GPIO IRQ initialized")
		NRF_LOG_INFO("waiting to initialize ppi link...")
		NRF_LOG_FLUSH();
		nrf_delay_ms(1000);
		
		ppi_init();
		
		NRF_LOG_INFO("ppi link initialized")
		NRF_LOG_FLUSH();
		
		for (;;)
        {
            //GPIOTE_IRQHandler();
			idle_state_handle();
			NRF_LOG_INFO("GPIOTE EVENTS IN: %i", NRF_GPIOTE->EVENTS_IN[1])
        }
}

Above is my code. I am using Keil uVision5 IDE on Windows 10. I am flashing s132 and then application hex to device using nRFGo.

My goal is to take a square wave as input to the nRF52 DK and measure the duration of each high and low in the signal (in microseconds) storing them into a queue for later processing.

Input signal is around 980 Hz. 

My code currently seems configured incorrectly.

NRF_GPIOTE->EVENTS[1] is always 0 according to the RTT logs. Even when multitudes of different input signals have been tried. 

I feel my lack of experience in working with the nRF52 is the root cause. 

I would appreciate anyone with GPIOTE and PPI experience taking time to review my short code snippet and diagnose my issues. 

Cheers!

Parents
  • You're clearing EVENTS_IN[1] in interrupt handler, so you will always see 0 in main thread. In general your code is correct. Does your GPIOTE_IRQHandler get called?

    What input signal do you have - push-pull or open-drain?

  • I do not believe my GPIOTE_IRQHandler function is ever being called. My RTT log never contains the line from the handler:

    NRF_LOG_INFO("in GPIOTE_IRQHandler...");

    When I was first building the project, the function definition for GPIOTE_IRQHandler() was getting an error because it was claiming to be already defined in nrfx_gpiote.c (line 668) as void nrfx_gpiote_irq_handler(void). 

    I commented this function out as that is what I saw people saying to do in DevZone question answers.

    I'm not sure if that could be causing my handler to not be called every polarity toggle on the input pin.

    I have tried various input signal settings with a function generator. None seem to trigger the handler:

    Frequencies Tested: 1 Hz to 1000 Hz

    Polarities tested: normal & inverted

    ----------------------

    Specific Setting Combinations tried to trigger event:

    ----------------------

    Amplitude (6.6v pk-pk)

    Load type: Hi-Z (High Impedance)

    ----------------------

    Amplitude (3.3v pk-pk)

    Load type: 50 Ohm resistance

    ---------------------

    Amplitude (3.3v pk-pk)

    Offset: 1.65v (in effort to get clear distinction between high and low)

    Load type: 50 Ohm resistance

Reply
  • I do not believe my GPIOTE_IRQHandler function is ever being called. My RTT log never contains the line from the handler:

    NRF_LOG_INFO("in GPIOTE_IRQHandler...");

    When I was first building the project, the function definition for GPIOTE_IRQHandler() was getting an error because it was claiming to be already defined in nrfx_gpiote.c (line 668) as void nrfx_gpiote_irq_handler(void). 

    I commented this function out as that is what I saw people saying to do in DevZone question answers.

    I'm not sure if that could be causing my handler to not be called every polarity toggle on the input pin.

    I have tried various input signal settings with a function generator. None seem to trigger the handler:

    Frequencies Tested: 1 Hz to 1000 Hz

    Polarities tested: normal & inverted

    ----------------------

    Specific Setting Combinations tried to trigger event:

    ----------------------

    Amplitude (6.6v pk-pk)

    Load type: Hi-Z (High Impedance)

    ----------------------

    Amplitude (3.3v pk-pk)

    Load type: 50 Ohm resistance

    ---------------------

    Amplitude (3.3v pk-pk)

    Offset: 1.65v (in effort to get clear distinction between high and low)

    Load type: 50 Ohm resistance

Children
  • I don't think supplying pin with 6.6v is a good idea :)

    Can you also print input value (nrf_gpio_pin_read(PIN_IN)) with RTT?

  • In main.c for loop: NRF_LOG_INFO("PIN_IN value: %i",nrf_gpio_pin_read(PIN_IN))

    Pin read on PIN_IN is always 1 if configured as nrf_gpio_cfg_input(PIN_IN, NRF_GPIO_PIN_PULLUP);

    Pin read on PIN_IN is always 0 if configured as nrf_gpio_cfg_input(PIN_IN, NRF_GPIO_PIN_PULLDOWN);

    Pin read on PIN_IN is always 0 if configured as nrf_gpio_cfg_input(PIN_IN, NRF_GPIO_PIN_NOPULL);

    This seems to point to me having my waveform generator input signal incorrectly configured???

    I'm also printing my queue size in main as well to see if anything ever gets queued. Its always 0 as well. 

  • You're trying to receive analog signal on digital input. It shouldn't be done such way. GPIO expects digital signal in range 0...VDD. For analog signal, configure pin as analog input and use COMP instead of GPIO. In any case input level should be in range 0...VDD, otherwise you need external schematic to ensure that.

    Try to connect your pin to GND then VDD, if there's no change in read value, your chip rather didn't withstand 6.6v input.

Related