how to disconnect a GPIO pin

i have a custom board that uses a nrf5340 that has been hardware modified so i can work again on getting my board to draw the mimimum power from the battery.

i have a PPK2 kit to measure the power i am drawing.

right now in SYSTEM_OFF state I am drawing about 600 ua..

i have several chips on the board that  use  a GPIO configured as an output pin to turn off a mosfet that controls their power.

when the chip does not have power it looks like it is getting power via other GPIO pins coming through the ESD diodes.

so I want to set all my GPIO pins that might be supply power to the unpowered IC on my board to be disconnected.

I am using zephyr and think I should use GPIO_DISCONNECTED.

I want the input buffer amplifier off

the output pin off

and any pullups off.

I do not want it to be detected by any interrupt.

I have one pin configured to work for wake on interrupt so I can press a button to wake my board up.

I worked on reducing my power months ago but gave up becuase teh hardware was pulling power beyond my control

now the hardware has been fixed but i still am drawing a lot of power due to i think the ESD diodes on unpowered chips.

thanks

phil

Parents Reply Children
  • Did you check with the multimeter as suggested by Susheel?

    weightwatcherphil said:

    would 

       gpio_pin_configure_dt( &shut_adc_ain0_, GPIO_INPUT);
    turn off the pullups ?

    As you have said, the pin is configured as output, and now you want to disconnect. Please have a look at GPIO port and pin details as in the product specification:

    For each pin, we have direction (telling whether it is configured as input or output), input (connected or not), drive strength and pull configurations. Please refer to GPIO registers where you can read the status of configuration by reading the appropriate registers.

    Below, I am reading P0.23 configuration using nrfjprog (a command line tool from Nordic)

    //NRFJPROG command to read P0.23 (that is Button0 on the DK) configuration
    nrfjprog --memrd 0x5084275C

    Also, I suggest to use "gpio_pin_configure()" rather than the gpio_pin_configure_dt(), as the later does the OR operation of new flags with previous flags, while the other sets the new flags.

    Below, I am reading all gpio port0 pin configurations before and after using gpio_pin_configure() function, and I can see that the correct configuration is taking place for that specific pin:

    Regards,

    Naeem

  • this is extremely helpful.  especially the part about the OR.

    i will run some more test when i get back from vacation.

    thanks

  • my boss wrote the following code 

    and it sets the pins like we want them.

    i want to do the same thing but use zephy commands.

    this code uses the nffx library.

    --Here is the routine.  It doesn't touch P0.24, P0.11 and sets the driver a little differently for the I2C pins (not exactly sure why that's needed, but it does help):
    
    int set_all_gpios_to_input_except_wake_up_and_power_control(void){
    
    
    
    
        printk("Put all GPIOS in DEFAULT state except the WAKEUP GPIO pin and the VDD control pin \n");
    
    
    
    
        for (int k=0;k<32;k++)
    
        {
    
            if ((k != 11) && (k != 24)) //P0.24 is the button so don't touch that.  P0.11 turns off the VDD, so don't touch that
    
                nrf_gpio_cfg_default(NRF_GPIO_PIN_MAP(0,k));
    
            if ((k <= 15))  //P1 only goes to 15
    
                if ((k==2) || (k==3))  //I2C pins handled differently for some reason, otherwise they consume extra power
    
                    nrf_gpio_cfg(NRF_GPIO_PIN_MAP(1,k),NRF_GPIO_PIN_DIR_INPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_S0D1, NRF_GPIO_PIN_NOSENSE);  //not sure why this is needed, but seems to be required for the I2C pins
    
                else
    
                    nrf_gpio_cfg_default(NRF_GPIO_PIN_MAP(1,k));
    
        }
    
        return true;
    
    }
    

    here is the code i have now.  i want to get _DT to work and avoid the call to 

                    nrf_gpio_cfg_default(NRF_GPIO_PIN_MAP(1,k));

    one thing we do not understand is why this line causes us to draw a lower current.

                    nrf_gpio_cfg(NRF_GPIO_PIN_MAP(1,k),NRF_GPIO_PIN_DIR_INPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_S0D1, NRF_GPIO_PIN_NOSENSE);  //not sure why this is needed, but seems to be required for the I2C pins

     

    int set_all_gpios_to_input_except_wake_up_and_power_control(void){
    
    	printk("put all GPIOS in INPUT state except the WAKEUP GPIO pin and the four power control pins \n");
    
        // pins used for power control
    	// leave these GPIOS alone.  They are in the OUTPUT state set to zero and control the power supplies
    	
    	//      PWR_EN   P0.21  //pwr5Ven    used to enable the 5V power so we ignore it since it is an output controlling the 5V power
    	//      CHG_EN_L P0.23  //chrgen     used to enable the charger so we ignore it since its an output controlling the charage enable
        //      VDD_ON   P0.11  //Vddon      used to enable teh VDD power so we ignore it since it is an output controlling the VDD power 
        //      AIN_EN   P1.06  //battmonitoren     used to enable battery monitor circuit so we ignore it since it is an output controlling battery monitor circuit 
    
    
    	// put the GPIOS in their lowest power state
    	// pins used by ADC
    	// 		AIN_CURRENT  AIN0 P0.04
    	//      AIN_REV      AIN2 P0.06
    	// 		AIN_BATTERY  AIN3 P0.07
    	// 		AIN_5V       AIN7 P0.28
    	static const struct gpio_dt_spec    shut_adc_ain0_ = GPIO_DT_SPEC_GET( DT_NODELABEL( adc_ain0 ), gpios );
    	static const struct gpio_dt_spec    shut_adc_ain2_ = GPIO_DT_SPEC_GET( DT_NODELABEL( adc_ain2 ), gpios );
        static const struct gpio_dt_spec    shut_adc_ain3_ = GPIO_DT_SPEC_GET( DT_NODELABEL( adc_ain3 ), gpios );
        static const struct gpio_dt_spec    shut_adc_ain7_ = GPIO_DT_SPEC_GET( DT_NODELABEL( adc_ain7 ), gpios );
    
        gpio_pin_configure_dt( &shut_adc_ain0_, GPIO_INPUT);
    	gpio_pin_configure_dt( &shut_adc_ain2_, GPIO_INPUT);
        gpio_pin_configure_dt( &shut_adc_ain3_, GPIO_INPUT);
        gpio_pin_configure_dt( &shut_adc_ain7_, GPIO_INPUT) ;
    
    	// pins used by I2c
    	// 		I2C_SCL P1.03
    	//      I2C_SDA P1.02
    
    	static const struct gpio_dt_spec    shut_i2c_scl_ = GPIO_DT_SPEC_GET( DT_NODELABEL( i2c_scl ), gpios );
        static const struct gpio_dt_spec    shut_i2c_sda_ = GPIO_DT_SPEC_GET( DT_NODELABEL( i2c_sda ), gpios );
    
        gpio_pin_configure_dt( &shut_i2c_scl_, GPIO_INPUT);
        gpio_pin_configure_dt( &shut_i2c_sda_, GPIO_INPUT);
    
    
    	// pins used by DA7281 PWM
    	//      J1_PWM P0.22
    	//      J2_PWM P0.09
    	//      J3_PWM P0.08
    	//      J4_PWM P0.12
    
    
    	static const struct gpio_dt_spec    shut_j1_pwm_ = GPIO_DT_SPEC_GET( DT_NODELABEL( j1_pwm ), gpios );
        static const struct gpio_dt_spec    shut_j2_pwm_ = GPIO_DT_SPEC_GET( DT_NODELABEL( j2_pwm ), gpios );
        static const struct gpio_dt_spec    shut_j3_pwm_ = GPIO_DT_SPEC_GET( DT_NODELABEL( j3_pwm ), gpios );
        static const struct gpio_dt_spec    shut_j4_pwm_ = GPIO_DT_SPEC_GET( DT_NODELABEL( j4_pwm ), gpios );
    
        gpio_pin_configure_dt( &shut_j1_pwm_, GPIO_INPUT);
        gpio_pin_configure_dt( &shut_j2_pwm_, GPIO_INPUT);
        gpio_pin_configure_dt( &shut_j3_pwm_,GPIO_INPUT) ;
    	gpio_pin_configure_dt( &shut_j4_pwm_,GPIO_INPUT) ;
    
    	//      J1_IRQ_L P1.09  //DA7281 interrupt not use in code
    	//      J2_IRQ_L P1.04  //DA7281 interrupt not use in code
    	//      J3_IRQ_L P0.20  //DA7281 interrupt not use in code
    	//      J4_IRQ_L P1.05  //DA7281 interrupt not use in code
    	static const struct gpio_dt_spec shut_irqt1 = GPIO_DT_SPEC_GET(DT_ALIAS(irqt1), gpios);
    	static const struct gpio_dt_spec shut_irqt2 = GPIO_DT_SPEC_GET(DT_ALIAS(irqt2), gpios);
    	static const struct gpio_dt_spec shut_irqt3 = GPIO_DT_SPEC_GET(DT_ALIAS(irqt3), gpios);
    	static const struct gpio_dt_spec shut_irqt4 = GPIO_DT_SPEC_GET(DT_ALIAS(irqt4), gpios);
    	gpio_pin_configure_dt(&shut_irqt1, GPIO_INPUT);
        gpio_pin_configure_dt(&shut_irqt2, GPIO_INPUT);
        gpio_pin_configure_dt(&shut_irqt3, GPIO_INPUT);
        gpio_pin_configure_dt(&shut_irqt4, GPIO_INPUT);
    
    	//      J1_DETECT P0.30 //tactor jack detect
    	//      J2_DETECT P1.10 //tactor jack detect
    	//      J3_DETECT P1.13 //tactor jack detect
    	//      J4_DETECT P0.10 //tactor jack detect
    
    		// Discrete inputs to detect if fingers F1-F4 are connected
    	static const struct gpio_dt_spec shut_detectJ1 = GPIO_DT_SPEC_GET(DT_ALIAS(det1), gpios);
    	static const struct gpio_dt_spec shut_detectJ2 = GPIO_DT_SPEC_GET(DT_ALIAS(det2), gpios);
    	static const struct gpio_dt_spec shut_detectJ3 = GPIO_DT_SPEC_GET(DT_ALIAS(det3), gpios);
    	static const struct gpio_dt_spec shut_detectJ4 = GPIO_DT_SPEC_GET(DT_ALIAS(det4), gpios);
    	gpio_pin_configure_dt(&shut_detectJ1, GPIO_INPUT);
        gpio_pin_configure_dt(&shut_detectJ2, GPIO_INPUT);
        gpio_pin_configure_dt(&shut_detectJ3, GPIO_INPUT);
        gpio_pin_configure_dt(&shut_detectJ4, GPIO_INPUT);
    
    
    	// pins used by the charger
    	//      PGOOD_L  P1.08
    	//      CHG_L    P0.31
    	
    
    	static const struct gpio_dt_spec shut_pwrGood = GPIO_DT_SPEC_GET(DT_ALIAS(powergood), gpios);
    	static const struct gpio_dt_spec shut_chrgIng = GPIO_DT_SPEC_GET(DT_ALIAS(chargingactive), gpios);
    
        gpio_pin_configure_dt(&shut_pwrGood, GPIO_INPUT);
        gpio_pin_configure_dt(&shut_chrgIng, GPIO_INPUT);
    
    	// pins used by RGB led
    	//		LED_R P1.14
    	//      LED_G P1.15
    	//      LED_B P1.12
    
    	static const struct gpio_dt_spec    shut_rgb_red_   = GPIO_DT_SPEC_GET( DT_NODELABEL( rgb_red_led ), gpios );
        static const struct gpio_dt_spec    shut_rgb_green_ = GPIO_DT_SPEC_GET( DT_NODELABEL( rgb_green_led ), gpios );
        static const struct gpio_dt_spec    shut_rgb_blue_  = GPIO_DT_SPEC_GET( DT_NODELABEL( rgb_blue_led ), gpios );
    
        gpio_pin_configure_dt( &shut_rgb_red_, GPIO_INPUT) ;
        gpio_pin_configure_dt( &shut_rgb_green_, GPIO_INPUT) ;
        gpio_pin_configure_dt( &shut_rgb_blue_,GPIO_INPUT) ;
    
    
    	// pins used for button (it genertes an interrupt also is the wake up pin)
        // PUSH_BTN  P0.24
    	// P0.23 (sw0) reserved
    	//static const struct gpio_dt_spec shut_sw0 = GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios);
    	// LEAVE the WAKE UP GPIO alone  (sw1)
    	//static const struct gpio_dt_spec shut_sw1 = GPIO_DT_SPEC_GET(DT_ALIAS(sw1), gpios);
    	
    	//gpio_pin_configure_dt(&shut_sw0, GPIO_INPUT);
     	//gpio_pin_configure_dt(&shut_sw1, GPIO_INPUT);
    
    	//pins used by the fuel gauge
    
    	static const struct gpio_dt_spec shut_alarmb = GPIO_DT_SPEC_GET(DT_ALIAS(alarmb), gpios);
    	gpio_pin_configure_dt(&shut_alarmb, GPIO_INPUT);
    
    
    
    // pins used by ISO TP10 TP11
    	//      TP_DBG_02 TP11 P1.01
    	//      TP_DBG_01 TP10 P1.00
    	//      TP_DBG_03 TP19 P1.07
    	//      TP_DBG_04 TP20 P1.11
    	static const struct gpio_dt_spec shut_tp10 = GPIO_DT_SPEC_GET(DT_ALIAS(tp10), gpios);
    	static const struct gpio_dt_spec shut_tp11 = GPIO_DT_SPEC_GET(DT_ALIAS(tp11), gpios);
    	static const struct gpio_dt_spec shut_tp19 = GPIO_DT_SPEC_GET(DT_ALIAS(tp19), gpios);
    	static const struct gpio_dt_spec shut_tp20 = GPIO_DT_SPEC_GET(DT_ALIAS(tp20), gpios);	
    
        //gpio_pin_configure_dt(&shut_tp10, GPIO_INPUT);
    	gpio_pin_configure_dt(&shut_tp10, GPIO_DISCONNECTED);
        gpio_pin_configure_dt(&shut_tp11, GPIO_DISCONNECTED);	
    	gpio_pin_configure_dt(&shut_tp19, GPIO_DISCONNECTED);
    	gpio_pin_configure_dt(&shut_tp20, GPIO_DISCONNECTED);
    
    	
        //USB   these are not GPIOs
    	//      D_P  H5 ignored
    	//      D_N  G5 ignored
    
    
    	//qspi
    	//  QSPI_CS	  P0.18   //flash CS
    	//  QSPI_CLK  P0.17   //flash CLK
    	//  QSPI_0    P0.13   //flash SI
    	//  QSPI_1    P0.14   //flash SO
    	//  QSPI_2    P0.15   //flash WP
    	//  QSPI_3    P0.16   //flash RST
    	static const struct gpio_dt_spec shut_flash_cs_  = GPIO_DT_SPEC_GET( DT_NODELABEL(flash_cs), gpios);
    	static const struct gpio_dt_spec shut_flash_clk_ = GPIO_DT_SPEC_GET( DT_NODELABEL(flash_clk), gpios);
    	static const struct gpio_dt_spec shut_flash_si_  = GPIO_DT_SPEC_GET( DT_NODELABEL(flash_si), gpios);
    	static const struct gpio_dt_spec shut_flash_so_  = GPIO_DT_SPEC_GET( DT_NODELABEL(flash_so), gpios);
        static const struct gpio_dt_spec shut_flash_wp_  = GPIO_DT_SPEC_GET( DT_NODELABEL(flash_wp), gpios);
    	static const struct gpio_dt_spec shut_flash_rst_ = GPIO_DT_SPEC_GET( DT_NODELABEL(flash_rst), gpios);
    
    
    
        gpio_pin_configure_dt( &shut_flash_cs_, GPIO_INPUT); //flash CS
    	gpio_pin_configure_dt( &shut_flash_clk_, GPIO_INPUT); //flash CLK
    	gpio_pin_configure_dt( &shut_flash_si_, GPIO_INPUT); // Flash SI
    	gpio_pin_configure_dt( &shut_flash_so_, GPIO_INPUT); // flash SO
    	gpio_pin_configure_dt( &shut_flash_wp_, GPIO_INPUT); // flash WP
    	gpio_pin_configure_dt( &shut_flash_rst_, GPIO_INPUT); // flash RST
    
    
    	//take care of unused pins
    	static const struct gpio_dt_spec shut_led3_  = GPIO_DT_SPEC_GET( DT_NODELABEL(led3), gpios);
    	static const struct gpio_dt_spec shut_adc_ain1_ = GPIO_DT_SPEC_GET( DT_NODELABEL( adc_ain1 ), gpios );
    	static const struct gpio_dt_spec shut_adc_ain4_ = GPIO_DT_SPEC_GET( DT_NODELABEL( adc_ain4 ), gpios );
    	static const struct gpio_dt_spec shut_adc_ain5_ = GPIO_DT_SPEC_GET( DT_NODELABEL( adc_ain5 ), gpios );
    	static const struct gpio_dt_spec shut_adc_ain6_ = GPIO_DT_SPEC_GET( DT_NODELABEL( adc_ain6 ), gpios );
    
    	gpio_pin_configure_dt( &shut_led3_, GPIO_INPUT); //led3 - unused pin
    	gpio_pin_configure_dt( &shut_adc_ain1_, GPIO_INPUT); //AIN1 - unused pin
    	gpio_pin_configure_dt( &shut_adc_ain4_, GPIO_INPUT); //AIN4 - unused pin
    	gpio_pin_configure_dt( &shut_adc_ain5_, GPIO_INPUT); //AIN5 - unused pin
    	gpio_pin_configure_dt( &shut_adc_ain6_, GPIO_INPUT); //AIN6 - unused pin
    
    
    
    	return true;
    }

Related