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

P0.18 resets device if driven high

I have an input connected to P0.18 on my nRF52832, which needs to be driven high by an external source.  I am running into two problems, which may or may not be related:

1) If I configure it as follows, with either NRF_GPIO_PIN_NOPULL or NRF_GPIO_PIN_PULLDOWN, and then drive that input high, a large amount of current passes through the pin, and the device resets due to low supply voltage. Here is that configuration:

nrf_drv_gpiote_in_config_t trigger_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);
trigger_config.pull = NRF_GPIO_PIN_NOPULL;
err_code = nrf_drv_gpiote_in_init(TRIGGER_INTERRUPT_PIN, &trigger_config, in_pin_handler);
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_in_event_enable(TRIGGER_INTERRUPT_PIN, true);
APP_ERROR_CHECK(err_code);

2) I want to use a handler for this ("B") and a second input ("A").  If I configure P0.18 with a pull-up, and then drive it low (by shorting the pin to ground), there's no reset.  However an interrupt on B will make the gpiote miss the next interrupt on A, i.e. the interrupt will not be called when A goes from low to high.  Here is that configuration, along with the handler:

static void gpio_init(){
	ret_code_t err_code;
	err_code = nrf_drv_gpiote_init();

	nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_LOTOHI(false);
	in_config.pull = NRF_GPIO_PIN_NOPULL;

	err_code = nrf_drv_gpiote_in_init(GYRO_INTERRUPT_PIN, &in_config, in_pin_handler);
	APP_ERROR_CHECK(err_code);

	nrf_drv_gpiote_in_config_t trigger_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);
	trigger_config.pull = NRF_GPIO_PIN_NOPULL;
	err_code = nrf_drv_gpiote_in_init(TRIGGER_INTERRUPT_PIN, &trigger_config, in_pin_handler);
	APP_ERROR_CHECK(err_code);
	nrf_drv_gpiote_in_event_enable(TRIGGER_INTERRUPT_PIN, true);
	APP_ERROR_CHECK(err_code);
}


void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action){
	//ret_code_t ret_code = NRF_SUCCESS;
	if(pin == GYRO_INTERRUPT_PIN){
		if(action == NRF_GPIOTE_POLARITY_LOTOHI){
			//read_gyro_fifo();
			//printf("Low -> High!\r\n");
			task_flags |= (1<<TASK_POLL_GYRO);
		}else if(NRF_GPIOTE_POLARITY_HITOLO){
			//printf("High -> Low!\r\n");
		}else{
			//printf("Toggle!\r\n");
		}

	}else{
		printf("t\r\n");
	}
}

So I have two questions:

  1. Is there something special about P0.18?  I haven't run into any of these types of issues on other gpio pins.
  2. Is it possible for the gpiote library from the SDK to somehow miss one pin changing while it's running the handler for another pin?

EDIT: If I configure the pin just as a plain input, without GPIOTE, and poll it, I see the same problems as in #1 above--if it's configured with a pull-up, it's fine, but if it has a pull-down or NOPULL, it resets when driven high.

EDIT #2: I believe I have resolved issue #1.  Should I post the second issue separately?

  • What is connected to SWO? I ask since it may be connected to a debug tool or other device, since SWO happens to be P0.18 and is used as an output for debug ot trace, see below; if the pin is driving high and it is pulled low externally it can force the power rail into current limit which causes the voltage dip and subsequent device reset.

    void SystemInit(void)
    {
        /* Enable SWO trace functionality. If ENABLE_SWO is not defined, SWO pin will be used as GPIO (see Product
           Specification to see which one). */
        #if defined (ENABLE_SWO)
            CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
            NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Serial << CLOCK_TRACECONFIG_TRACEMUX_Pos;
            NRF_P0->PIN_CNF[18] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
        #endif
    
        /* Enable Trace functionality. If ENABLE_TRACE is not defined, TRACE pins will be used as GPIOs (see Product
           Specification to see which ones). */
        #if defined (ENABLE_TRACE)
            CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
            NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Parallel << CLOCK_TRACECONFIG_TRACEMUX_Pos;
            NRF_P0->PIN_CNF[14] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
            NRF_P0->PIN_CNF[15] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
            NRF_P0->PIN_CNF[16] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
            NRF_P0->PIN_CNF[18] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
            NRF_P0->PIN_CNF[20] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
        #endif
    

  • I looked into that earlier.  ENABLE_SWO is not defined anywhere in the project as far as I can tell (Eclipse has it greyed out).  Nothing else is connected to that pin--it's on an external target, so only VTG, GND, SWDIO and SWCLK are connected to anything external.

  • I don't mean to be pedantic, but the definitions are not in c or h files but in the project file - if used; I know someone was caught out by this (ie me). Your scenario matches exactly ..

Related