This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

GPIOTE Output Pin High/Low Is Reversed (LED Blinking Test)

Good evening,

From testing my Nano 33 BLE, I've discovered that the following settings are reversed with respect to "High" and "Low", i.e., LEDs light up for Low, and turn off for High Confused

For testing purposes I'm running the following program compiled using Arduino's IDE and source files... PPI Toggle Test (I've also included it just below; virtually exactly the same as via the link).

For the following program it becomes apparent when GPIOTE_CONFIG_OUTINIT_Low is changed to GPIOTE_CONFIG_OUTINIT_High, but it's the same for NRF_GPIOTE->TASKS_CLR and NRF_GPIOTE->TASKS_SET for which CLR turns the LED on and SET turns it off.

I can work like this if I need to, but I'm hoping that I've just missed something silly. Therefore please can someone help?

This is my test program via the above link...

#include <nrf.h>

#define PPI_CHANNEL (0)
// #define PIN_GPIO (11)
#define PIN_GPIO (16) // Green LED on Nano 33 BLE

void setup()
{	
	// Configure PIN_GPIO as output
	// ----------------------------
	NRF_GPIO->DIRSET = (1UL << PIN_GPIO);
	
	// Configure GPIOTE->TASKS_OUT[0] to toggle PIN_GPIO
	// -------------------------------------------------
	NRF_GPIOTE->CONFIG[0] =
	
	(GPIOTE_CONFIG_MODE_Task       	    << GPIOTE_CONFIG_MODE_Pos) |
	(GPIOTE_CONFIG_OUTINIT_Low   		<< GPIOTE_CONFIG_OUTINIT_Pos) |
	(GPIOTE_CONFIG_POLARITY_Toggle 	   	<< GPIOTE_CONFIG_POLARITY_Pos) |
	(PIN_GPIO                     		<< GPIOTE_CONFIG_PSEL_Pos);
	
	// Configure TIMER0 to generate EVENTS_COMPARE[0] every 2000000us
	// -----------------------------------------------------------
	NRF_TIMER0->BITMODE = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos;
	NRF_TIMER0->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos;
	NRF_TIMER0->PRESCALER = 4;
	NRF_TIMER0->CC[0] = 2000000;
	NRF_TIMER0->TASKS_START = 1;
	
	// Configure PPI channel with connection between TIMER->EVENTS_COMPARE[0] and GPIOTE->TASKS_OUT[0]
	// -----------------------------------------------------------------------------------------------
	NRF_PPI->CH[PPI_CHANNEL].EEP = (uint32_t)&NRF_TIMER0->EVENTS_COMPARE[0];
	NRF_PPI->CH[PPI_CHANNEL].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
	
	// Enable PPI channel
	// ------------------
	NRF_PPI->CHENSET = (1UL << PPI_CHANNEL);
}
	
void loop()
{
	while (1)
	{
		__WFE();
	}
}

Thank you, Gary.

EDIT... Here's my NRF_GPIOTE->TASKS_SET and NRF_GPIOTE->TASKS_CLR test program.

Each time the LED should turn on it starts timer 3, which then should turn the LED off after 0.5 seconds. But instead what actually happens is, each time the LED turns on, 1.5 seconds (because timer 0 has already been running for 0.5 seconds) later GPIOTE->TASKS_SET turns it off. But that means SET and CLR are each doing the opposite to what they're suppose to do...

When I change _SET to _CLR and _CLR to _SET it then works as expected.

Here's the program...

#include <nrf.h>

#define PPI_CHANNEL_0 (0)
#define PPI_CHANNEL_1 (1)

// #define PIN_GPIO (11)
#define PIN_GPIO (16) // Green LED on Nano 33 BLE	

/* Using Timer 1 crashes the board... so don't use it */

void setup()
{
	// Configure PIN_GPIO as output
	// ----------------------------
	NRF_GPIO->DIRSET = (1UL << PIN_GPIO);
	
	// Configure GPIOTE
	// ----------------
	NRF_GPIOTE->CONFIG[0] =
	
	(GPIOTE_CONFIG_MODE_Task      << GPIOTE_CONFIG_MODE_Pos) |
	(PIN_GPIO                     << GPIOTE_CONFIG_PSEL_Pos);		
	
	// Configure TIMER0 & TIMER3 to generate EVENTS_COMPARE[0] every 2000000us and 500000us respectively
	// -------------------------------------------------------------------------------------------------
	NRF_TIMER0->BITMODE = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos;
	NRF_TIMER0->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos;		
	NRF_TIMER0->PRESCALER = 4;			
	NRF_TIMER0->CC[0] = 2000000;				
	NRF_TIMER0->TASKS_START = 1;		
	
	NRF_TIMER3->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
	NRF_TIMER3->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos;
	NRF_TIMER3->PRESCALER = 4;
	NRF_TIMER3->CC[0] = 500000;		
	
	// Configure PPI channels with connection between TIMER->EVENTS_COMPARE[0] and GPIOTE->TASKS_SET[0] and GPIOTE->TASKS_CLR[0]
	// -------------------------------------------------------------------------------------------------------------------------
	NRF_PPI->CH[PPI_CHANNEL_0].EEP = (uint32_t) & NRF_TIMER0->EVENTS_COMPARE[0];
	NRF_PPI->CH[PPI_CHANNEL_0].TEP = (uint32_t) & NRF_GPIOTE->TASKS_SET[0];		
	NRF_PPI->FORK[PPI_CHANNEL_0].TEP = (uint32_t) & NRF_TIMER3->TASKS_START;
	
	NRF_PPI->CH[PPI_CHANNEL_1].EEP = (uint32_t) & NRF_TIMER3->EVENTS_COMPARE[0];
	NRF_PPI->CH[PPI_CHANNEL_1].TEP = (uint32_t) & NRF_GPIOTE->TASKS_CLR[0];		
	NRF_PPI->FORK[PPI_CHANNEL_1].TEP = (uint32_t) & NRF_TIMER3->TASKS_STOP;		
	
	// Enable PPI channel
	// ------------------
	NRF_PPI->CHENSET = (1UL << PPI_CHANNEL_0);
	NRF_PPI->CHENSET = (1UL << PPI_CHANNEL_1);
}

void loop()
{			 
	while (1)
	{
		__WFE();
	}
}

  • I found an explanation here... nRF52840 Development Kit (User Guide) (See quote below from page 30 of the guide)

    "The LEDs are active low, meaning that writing a logical zero ('0') to the output pin will illuminate the LED"

    Edit... My apologies. I was wrong before, i.e., the High/Low is Not reversed...

    Incidentally, I've had a USB PicoScope for about 1 week, and finally have the chance to play around a little more this afternoon. So, after a quick Google search I found that I needed to add "Port  << GPIOTE_CONFIG_PORT_Pos" to test other than via LEDs.

    So for pin D10 (P1.02), the following is required... PIN_GPIO (2) and Port (1). I now have my PicoScope set to 2 s/div and +2 V, and I can clearly see the High and Low occurring correctly.

    Problem solved Grinning 

Related