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

Reduce GPIO current draw

Hi there, 

We are currently developing and testing on the nRF5340. We are using our own OS (not Zephyr).

We measure power on the devkit by connecting the PPK2 as a source meter to the external supply, and then switching SW10 (VEXT->NRF) switch to on. 

With the above setup, we measure a current of 2uA when the device goes into System Off mode, and about 11uA in System On Low power mode. The only peripherals running are the RTC and the watchdog.

However when we use the GPIO peripheral, the current draw shoots up to 270uA when the device goes into System On Low Power mode. This seems extremely high, and we are not able to get this current down. This is the steps we performed on the GPIO peripheral:

1) Set LED1 pin as output

2) Set button1 as input and enable the interrupt for it

3) The interrupt service routine then toggles the LED.

NRF_P0_S->PIN_CNF[28] = (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) | //Set LED1
                                   (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
                                   (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
                                   (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
                                   (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
    
NRF_P0_S->PIN_CNF[23] = (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | // Configure Button 1 dev kit as input with pull-up resistor enabled.
                                   (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
                                   (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
                                   (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) |
                                   (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
      
NRF_GPIOTE0_S->CONFIG[0] =    (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) |
                                            (23 << GPIOTE_CONFIG_PSEL_Pos) |
                                            (GPIOTE_PORT << GPIOTE_CONFIG_PORT_Pos) |
                                            (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);
    
NRF_GPIOTE0_S->INTENSET = GPIOTE_INTENSET_IN0_Set << GPIOTE_INTENSET_IN0_Pos;
    
NVIC_SetPriority(GPIOTE0_IRQn, (uint32_t) ISR_PRIORITY_RAIL);
NVIC_EnableIRQ(GPIOTE0_IRQn);

void GPIOTE0_IRQHandler(void)
{
    if(NRF_GPIOTE0_S->EVENTS_IN[0])
    {
      NRF_GPIOTE0_S->EVENTS_IN[0] = 0;
      
      if(NRF_P0_S->OUT & (1 << LED1_PIN))
      {
        NRF_P0_S->OUTCLR = (1UL << LED1_PIN);
      }
      else      
      {
        NRF_P0_S->OUTSET = (1UL << LED1_PIN);
      }
    }
}

This works as expected, however current draw is 270uA in System On Low Power mode, regardless of the state of the LED, which seems extremely high. How can we reduce the current draw? We execute the following to allow the processor to go into low power:

    NRF_POWER_S->TASKS_LOWPWR = 1U;     //Enable low power mode
    
    __DSB();
    __WFE();

Kind regards,

Frikkie

  • Hi,

    I would strongly recommend that you use nRF Connect SDK.

    1) Set LED1 pin as output

    2) Set button1 as input and enable the interrupt for it

    3) The interrupt service routine then toggles the LED.

    Do you see this only when you do all these steps? What if e.g. only set button 1 as input, or only set LED1 as output?

  • Hi Sigurd, 

    Setting ONLY LED1 pin as output keeps the current stable at 11uA. Setting both the LED1 pin and Button1 pin as an output and input respectively, also keeps the current stable at 11uA.

    Only after we configure the GPIOTE peripheral to enable the interrupts (as shown in the code of the initial post), the current jumps up into the 270uA range. Its almost as if the device can not go into a low power state while waiting for an interrupt to occur?

    Please advise?

  • Hi,

    Are you using DCDC mode on app, net, HV regulators?
    How is the chip powered?
    What voltage is the chip powered at? Are you using VDD or VDDH?
    Have you made sure that errata workarounds from the MDK is being enabled and used properly in your OS ?

  • Hi, I would expect to see 50-70 uA with the code you posted. It's using the GPIOTE IN event which will add some additional current. You can use the PORT event instead, which should not add anything to the system on idle current

    You use the SENSE bits in the PIN_CNF register to enable GPIO sensing, and then enable the PORT interrupt in the GPIOTE module:

    NRF_P0->PIN_CNF[23] = (3 << 2) | (3 << 16); // pin 23, pullup, sense high to low
    NRF_GPIOTE->INTENSET = (1 << 31); // enable PORT interrupt

    Here is a fully working "bare metal" sample that at least works when using Zephyr. When I run it here I measure about 3 uA. It turns off the LED (pin 28) when the button (pin 23) is pressed.

    I see that you are not using Zephyr, but the principle should be the same. Just remove the IRQ_CONNECT macro, and use the GPIOTE0_IRQHandler as you already are doing..

    #include <zephyr.h>

    void gpiote_irq_handler(void){
        NRF_GPIOTE->EVENTS_PORT = 0; //clear PORT event
        NRF_GPIOTE->INTENSET = 0; // disable PORT interrupt
        NRF_P0->OUTSET = (1 << 28); // Turn off LED
    }
    void main(void)
    {
        IRQ_CONNECT(DT_IRQN(DT_NODELABEL(gpiote)), DT_IRQ(DT_NODELABEL(gpiote), priority), gpiote_irq_handler, NULL, 0); //connect interrupt handler above in zephyr
        irq_enable(DT_IRQN(DT_NODELABEL(gpiote))); //enable GPIOTE interrupts
        NRF_P0->DIRSET = (1 << 28); // LED pin output
        NRF_P0->OUTCLR = (1 << 28); // Turn on LED
        NRF_P0->PIN_CNF[23] = (3 << 2) | (3 << 16); // configure button, pin 23, pullup, sense high to low
        NRF_GPIOTE->INTENSET = (1 << 31); // enable PORT interrupt
    for(;;){
    __WFE();
    }
    }

    Please try this and see if you get down to normal idle current.

    Best regards,
    Stian

  • Hi, I realize now that you posted a separate case for the same topic which is handled by Hung. I will follow up there.

Related