No control over GPIO pins whilst having CONFIG_NRFX_GPIOTE enabled

Hello,

Currently we're working on improving our DALI driver on the nRF52832 chip, because we've experienced issues with transmitting DALI bits with the correct timing. The issues we experience are similar with a previous blog post here on the support channel.

Therefor, we are trying to solve this issues in a similar manner: by using a PPI channel to have a GPIOTE task trigger by a timer CC. We experienced a few issues using this method, our main issue being that the project configuration CONFIG_GPIO has to be disabled, else nrfx_gpiote_init() returns NRFX_ERROR_INVALID_STATE. Yet, we still want to be having control over (other) GPIO pins and be able to manually set them. We tried to use the nRF GPIO HAL driver, but when calling nrf_gpio_cfg_out() to set a GPIO pin as an output and then calling nrf_gpio_pin_set() no change in pin state is noticeable, for example when trying to turn on an LED on the nRF52832 devkit.

We've been working in a dev envoirment, where the following configurations are set:

CONFIG_GPIO=n
CONFIG_NRFX_GPIOTE=y
CONFIG_LOG=y
CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=100
CONFIG_UART_CONSOLE=y
CONFIG_NRFX_TIMER1=y

Could you let us know if it is possible to still have control over GPIO pins whilst having CONFIG_NRFX_GPIOTE enabled and if so, how?

Parents
  • Hi Rowan,

    Thankyou for contacting DevZone at NordicSemi.

    As per your provided information, I started with GPIOTE and configured button and led using PPI channel (button1 & led1).
    Next, I tried to enable CONFIG_GPIO and I was getting error for multiple interrupt entries. Nonetheless, I disabled the CONFIG_GPIO and tried to access certain GPIO pin using HAL GPIO (led3). I am toggling the led3 in a while loop using nrf_gpio_pin_toggle() function. Also, the button1 press enables the task and everything works as expected as you can see in the attached image.

    Sample Output: 

    I am attached this sample project just for reference. Maybe you can first do a prestine build and flash it on your (nrf52) DK, and then look at the code and/or modify accordingly.

    Sample Project Code: c_298584_gpiote.rar

    Let me know if this is something you wanted to do.

    Moreover, use of GPIO along with GPIOTE could have implications, that I might not be fully aware of, but I was able to use CONFIG_GPIO by using IRQ_DIRECT_CONNECT function instead of IRQ_CONNECT function.

    Hope it helps.
    Naeem

  • Hi Naeem,

    Thank you for your quick response! using IRQ_DIRECT_CONNECT instead of IRQ_CONNECT does allow me to build the project without any errors, yet I still get the same error message when calling function nrfx_gpiote_init:

    <err> nrfx: nrfx_gpiote_init error: 0bad0005

    Where 0bad0005 equals NRFX_ERROR_INVALID_STATE.

    Since some other parts of our project code are dependent on CONFIG_GPIO, We would like to have NRFX_GPIOTE working alongside with GPIO.

    Do you know how to solve this error?

Reply Children
  • Hi Rowan,

    In my previous reply, you can see that we can directly toggle (set and reset as well) a GPIO pin independently only using GPIOTE configuration enabled. Was that not something you wanted to do (using GPIOTE configuring event/task with pins and toggling another pin without event/task association)?

    As said earlier, configuring GPIO and GPIOTE simultaneously could have implications, and I do not know about your situation/error, but if you like you can send your minimal code and method to reproduce the error.

    Regards,

    Naeem

  • Hi Naeem,

    Yes, we want to be able to use GPIOTE to configure events/tasks with pins, and we want to be able to configure other GPIO pins (e.g. as output with pull-up, active high with high initial state). Now I do know that this is something you can do with HAL GPIO, however, this would mean we have to refactor code. Of course that would be something we can do, but would rather not.

    Therefore, I am curious about having GPIO configured alongside NRFX_GPIOTE and if that is possible. Like I said, my code is failing when trying to initialize GPIOTE with nrfx_gpiote_init when GPIO is enabled in the project configurations.

    We configure our GPIOTE like this:

    /* GPIOTE configurations */
    uint8_t dali_tx_gpiote_channel;
    /*Output task*/
    nrfx_gpiote_output_config_t gpiote_cfg = {
    		.drive = NRF_GPIO_PIN_S0S1,
    		.input_connect = NRF_GPIO_PIN_INPUT_DISCONNECT,
    		.pull = NRF_GPIO_PIN_NOPULL,
    };
    nrfx_gpiote_task_config_t task_config = {
    	.polarity = NRF_GPIOTE_POLARITY_TOGGLE,
    	.init_val = NRF_GPIOTE_INITIAL_VALUE_HIGH,
    };
    /* Input event */
    static void dali_rx_event_handler(nrfx_gpiote_pin_t pin, nrfx_gpiote_trigger_t trigger, void *p_context);
    nrfx_gpiote_input_config_t dali_rx_event_conf = {
    	.pull = NRF_GPIO_PIN_NOPULL,
    };
    nrfx_gpiote_trigger_config_t dali_rx_event_trigger_conf = {
    	.trigger = NRFX_GPIOTE_TRIGGER_TOGGLE,
    	.p_in_channel = NULL,
    };
    nrfx_gpiote_handler_config_t dali_rx_event_handler_conf = {
    	.handler = 	dali_rx_event_handler,
    	.p_context = NULL,
    };

    We initialize it like this:

    static void dali_gpiote_init(void) {
    	nrfx_err_t err;
    	/* Initialize GPIOTE (the interrupt priority passed as the parameter
    	 * here is ignored, see nrfx_glue.h).
    	 */
    	err = nrfx_gpiote_init(0);
    	if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_gpiote_init error: %08x", err);
    		return;
    	}
    	/* Configure DALI TX as output task */
    	err = nrfx_gpiote_channel_alloc(&dali_tx_gpiote_channel);
    	if (err != NRFX_SUCCESS) {
    		LOG_ERR("Failed to allocate dali tx gpiote channel: %08x", err);
    		return;
    	}
    	task_config.task_ch = dali_tx_gpiote_channel;
    	err = nrfx_gpiote_output_configure(OUTPUT_PIN, &gpiote_cfg, &task_config);
    	if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_gpiote_output_configure error: %08x", err);
    		return;
    	}
    	/* Configure DALI RX as input event */
    	err = nrfx_gpiote_input_configure(DALI_RX_GPIO, &dali_rx_event_conf, &dali_rx_event_trigger_conf, &dali_rx_event_handler_conf);
    	if (err != NRFX_SUCCESS) {
    		LOG_ERR("nrfx_gpiote_input_configure error: %08x", err);
    		return;
    	}
    	nrfx_gpiote_out_task_enable(OUTPUT_PIN);
    }

    Before initialization, we call:

    IRQ_DIRECT_CONNECT(DT_IRQN(DT_NODELABEL(gpiote)),
    		    	DT_IRQ(DT_NODELABEL(gpiote), priority),
    		    	nrfx_gpiote_irq_handler, 0);

    When CONFIG_GPIO=n, everything works accordingly, when GPIO_CONFIG=y, nrfx_gpiote_init fails.
    Please see our project configurations:

    CONFIG_GPIO=y
    CONFIG_NRFX_GPIOTE=y
    CONFIG_LOG=y
    CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=100
    CONFIG_UART_CONSOLE=y
    CONFIG_NRFX_TIMER1=y

    If you come to the conclusion that it is not possible to have GPIO configured alongside NRFX_GPIOTE, we will probably use HAL GPIO from nrf, but it would save us refactoring if this works!

    Regards,

    Rowan

  • Found the source of the issue! When CONFIG_GPIO and CONFIG_NRFX_GPIOTE are both enabled, nrfx_gpiote.c is automatically added as a target source in the CMakelists and by default will be initialized. The error returned by nrfx_gpiote_init makes perfect sense, since it is actually already initialized by default when CONFIG_GPIO is also enabled.

    By simply checking if the function is already initialized with nrfx_gpiote_is_init and only initializing gpiote when necessary solved the problem.

    Thank you for your help!

Related