NRF_GPIOTE->INTENSET = 1... Crashes with GPIOTE_CONFIG_POLARITY_LoToHi

Hi Everyone,

I'm having problems getting GPIOTE_IRQHandler_v() to run.

"NRF_GPIOTE->INTENSET = 1" causes my Nano 33 BLE to crash if "(GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos)" is enabled.

Otherwise it works as expected, i.e., when I connect an input signal from a 2nd Nano, "Serial.println("EVENTS_IN: Has Fired ++++")" executes successfully.

The following link is where I discovered how to set up the GPIOTE handler GPIOTE Handler

I'm compiling using the Arduino IDE and source files. Please let me know your ideas. Here's my program...

#include <nrf.h>

#define PIN_GPIO (2) // ~D10 = P1.02 ... Nano 33 BLE
#define PORT (1)

void setup()
{			
	Serial.begin(115200);
	
	// Configure PIN_GPIO as input
	// ---------------------------		
	NRF_GPIO->DIRSET = GPIO_DIRSET_PIN2_Input << GPIO_DIRSET_PIN2_Pos; // Not actually required based on "Input" being the default
	
	// Configure GPIOTE
	// ----------------
	NRF_GPIOTE->CONFIG[0] =
	
	(GPIOTE_CONFIG_MODE_Event   	<< GPIOTE_CONFIG_MODE_Pos) |
	(GPIOTE_CONFIG_POLARITY_LoToHi	<< GPIOTE_CONFIG_POLARITY_Pos) | // (Commenting this line stops the board crashing. But: GPIOTE_IRQHandler_v() still doesn't run) 
	(PORT                			<< GPIOTE_CONFIG_PORT_Pos) |     // (Although it's actually pointless commenting the above line because then no IN[n] events will be generated)
	(PIN_GPIO                       << GPIOTE_CONFIG_PSEL_Pos);		
	
	// NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN0_Set << GPIOTE_INTENSET_IN0_Pos (same as INTENSET = 1)
	NRF_GPIOTE->INTENSET = 1; // Set = 1 & [0] = Bit number 0 (Commenting this line stops the board crashing, which causes "EVENTS_IN: Has Fired ++++" to successfully be displayed periodically)		
	NVIC_EnableIRQ(GPIOTE_IRQn); 
}

volatile bool action = false;

extern "C" void GPIOTE_IRQHandler_v()
{			
	if (NRF_GPIOTE->EVENTS_IN[0] != 0)
	{
		NRF_GPIOTE->EVENTS_IN[0] = 0;			
		action = true;
	}
}

unsigned long currentTime = 0;
unsigned long previousTime = 0;
unsigned int deltaTime = 0;

void loop()
{		
	currentTime = micros();
	deltaTime += currentTime - previousTime;
	previousTime = currentTime; 
	
	if (deltaTime > 10000) // 100Hz
	{					
		deltaTime = 0;			
		
		if (NRF_GPIOTE->EVENTS_IN[0] != 0)
		{
			NRF_GPIOTE->EVENTS_IN[0] = 0;
			Serial.println("EVENTS_IN: Has Fired ++++");				
		}
		else
		    Serial.println("EVENTS_IN: Has Not Fired ---");
		
		if (action)
		{
			action = false;				
			Serial.println("In Action Loop ++++");
		}
		else
		    Serial.println("Not In Action Loop ---");
	}       
}

Parents
  • Isn't it a bit scary that both your interrupt handler and main are checking and clearing the NRF_GPIOTE->EVENTS_IN[0] event? I suggest that the interrupt handler will take of the interrupt, while it can use a global flag (in your case 'action') to inform main() that it was set. In other words comment out the handling of NRF_GPIOTE->EVENTS_IN[0] in the main() loop when checking the action flag.

    I also suggest that you disable the GPIOTE event interrupt when setting the action flag, and then in the main loop you can enable it again after handling the action flag. Else the GPIOTE_IRQHandler_v() may be continsouly triggering, preventing/delaying other processes from running, depending on the interrupt priority of GPIOTE_IRQHandler_v().

    Kenneth

  • As a test program designed to have two different methods for acknowledging an input signal after it has been received from another board, that honestly was intentional, i.e., I was expecting to see a random occurrence of the two Serial.println()s executing within loop(). Just to point out that 'action' is already being read/accessed as a global flag within loop(). Likewise, the EVENTS_IN[0] is being accessed in a global fashion within loop() too. I had already tested each method on its own.

    Anyway I've removed all the code down to a bare minimum to help better illustrate the problem. That is, the board is in a state of being crashed immediately after uploading the program, meaning that to recover it, the bootloader button needs pressing. Here's the minimal program... (Also, the board is actually crashed without any input signal from my 2nd Nano)

    #include <nrf.h>
    
    #define PIN_GPIO (2) // ~D10 = P1.02 ... Nano 33 BLE
    #define PORT (1)
    
    void setup()
    {			
    	Serial.begin(115200);
    	
    	// Configure PIN_GPIO as input
    	// ---------------------------		
    	NRF_GPIO->DIRSET = GPIO_DIRSET_PIN2_Input << GPIO_DIRSET_PIN2_Pos; // Not actually required based on "Input" being the default
    	
    	// Configure GPIOTE
    	// ----------------
    	NRF_GPIOTE->CONFIG[0] =
    	
    	(GPIOTE_CONFIG_MODE_Event   	<< GPIOTE_CONFIG_MODE_Pos) |
    	(GPIOTE_CONFIG_POLARITY_LoToHi	<< GPIOTE_CONFIG_POLARITY_Pos) | // (Commenting this line stops the board crashing. But: GPIOTE_IRQHandler_v() still doesn't run) 
    	(PORT                			<< GPIOTE_CONFIG_PORT_Pos) |     // (Although it's actually pointless commenting the above line because then no IN[n] events will be generated)
    	(PIN_GPIO                       << GPIOTE_CONFIG_PSEL_Pos);		
    	
    	// NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN0_Set << GPIOTE_INTENSET_IN0_Pos (same as INTENSET = 1)
    	NRF_GPIOTE->INTENSET = 1; // Set = 1 & [0] = Bit number 0 (Commenting this line stops the board crashing, which causes "EVENTS_IN: Has Fired ++++" to successfully be displayed periodically)		
    	NVIC_EnableIRQ(GPIOTE_IRQn); 
    }
    
    extern "C" void GPIOTE_IRQHandler_v()
    {			
    	
    }
    
    void loop()
    {		
    
    }

Reply
  • As a test program designed to have two different methods for acknowledging an input signal after it has been received from another board, that honestly was intentional, i.e., I was expecting to see a random occurrence of the two Serial.println()s executing within loop(). Just to point out that 'action' is already being read/accessed as a global flag within loop(). Likewise, the EVENTS_IN[0] is being accessed in a global fashion within loop() too. I had already tested each method on its own.

    Anyway I've removed all the code down to a bare minimum to help better illustrate the problem. That is, the board is in a state of being crashed immediately after uploading the program, meaning that to recover it, the bootloader button needs pressing. Here's the minimal program... (Also, the board is actually crashed without any input signal from my 2nd Nano)

    #include <nrf.h>
    
    #define PIN_GPIO (2) // ~D10 = P1.02 ... Nano 33 BLE
    #define PORT (1)
    
    void setup()
    {			
    	Serial.begin(115200);
    	
    	// Configure PIN_GPIO as input
    	// ---------------------------		
    	NRF_GPIO->DIRSET = GPIO_DIRSET_PIN2_Input << GPIO_DIRSET_PIN2_Pos; // Not actually required based on "Input" being the default
    	
    	// Configure GPIOTE
    	// ----------------
    	NRF_GPIOTE->CONFIG[0] =
    	
    	(GPIOTE_CONFIG_MODE_Event   	<< GPIOTE_CONFIG_MODE_Pos) |
    	(GPIOTE_CONFIG_POLARITY_LoToHi	<< GPIOTE_CONFIG_POLARITY_Pos) | // (Commenting this line stops the board crashing. But: GPIOTE_IRQHandler_v() still doesn't run) 
    	(PORT                			<< GPIOTE_CONFIG_PORT_Pos) |     // (Although it's actually pointless commenting the above line because then no IN[n] events will be generated)
    	(PIN_GPIO                       << GPIOTE_CONFIG_PSEL_Pos);		
    	
    	// NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN0_Set << GPIOTE_INTENSET_IN0_Pos (same as INTENSET = 1)
    	NRF_GPIOTE->INTENSET = 1; // Set = 1 & [0] = Bit number 0 (Commenting this line stops the board crashing, which causes "EVENTS_IN: Has Fired ++++" to successfully be displayed periodically)		
    	NVIC_EnableIRQ(GPIOTE_IRQn); 
    }
    
    extern "C" void GPIOTE_IRQHandler_v()
    {			
    	
    }
    
    void loop()
    {		
    
    }

Children
Related