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

Changing GPIOTE out pin level gives hard fault

I set up PPI so that it kicks off TWIM (I2C) transfer on GPIOTE pin transition low to high.  Everything works great, except that I also setup a fork task to set another GPIOTE out to high during the transaction.  I then wanted to clear that pin after the transaction has completed, but this throws a hard fault in nrfx_gpiote_out_clear on the assert that pin_in_use_by_te is false.  So I guess two questions:

  1. Why the hard fault here?  Is it to prevent accidentally triggering PPI by manually setting the pin?
  2. If I am only using the NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH (or LOW) task to change the output direction, how do I ever set it back low if I can't use nrfx_gpiote_out_clear?  Do I have to free the channel and reassign it every time I want to change the pin state manually?

Here is my code:

...
static void ppi_init(void)
{
    ...
    /* Configure LED GPIOTE to switch on when reading */
    nrfx_gpiote_out_config_t config1 = NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH;
    error = nrfx_gpiote_out_init(LED2, &config1);
    APP_ERROR_CHECK(error);
    nrfx_gpiote_out_task_enable(LED2);

    ...
    m_task_address_gpio_set = nrfx_gpiote_out_task_addr_get(LED2);
    ...
    
    /* Allocate a free PPI channel */
    error = nrfx_ppi_channel_alloc(&m_ppi_channel_twi_start);
    APP_ERROR_CHECK(error);

    /* Assign the event and task to the PPI */
    error = nrfx_ppi_channel_assign(m_ppi_channel_twi_start,
                                    m_event_address_gpiote_port,
                                    m_task_address_twi_start);
    APP_ERROR_CHECK(error);

    /* GPIO task to blink LED2 as fork */
    error = nrfx_ppi_channel_fork_assign(m_ppi_channel_twi_start,
                                         m_task_address_gpio_set);
    APP_ERROR_CHECK(error);

    /* Enable PPI channel for this T/E set */
    error = nrfx_ppi_channel_enable(m_ppi_channel_twi_start);
    APP_ERROR_CHECK(error);
}

int main(void)
{
    ...
    ppi_init();
    ...
    while(1)
    {
        if (twim_stopped_flag)
        {
            ...
            nrfx_gpiote_out_clear(LED2);
        }
    }
}

(P.S. No joke - I love the PPL system so much, I have a serious dev crush on it. <3 <3  Keep up the great work!)

Parents
  • Hi, 

    Is it to prevent accidentally triggering PPI by manually setting the pin?

    Looking at the gpiote driver it looks like it has some protection mechanism that prevent using nrf_gpio is not allowed while nrf_gpiote is controlling the pin, which I think make sense, because using nrf_gpio while nrf_gpiote is controlling the pin should have no effect on the output level. So you would need to uninit-init yes, unless you enable toggle task, in which case you could just trigger toggle task to revert the pin back to low level. You can always read the pin level to ensure you don't invert the level on the pin before calling toggle task.

    Kenneth

Reply
  • Hi, 

    Is it to prevent accidentally triggering PPI by manually setting the pin?

    Looking at the gpiote driver it looks like it has some protection mechanism that prevent using nrf_gpio is not allowed while nrf_gpiote is controlling the pin, which I think make sense, because using nrf_gpio while nrf_gpiote is controlling the pin should have no effect on the output level. So you would need to uninit-init yes, unless you enable toggle task, in which case you could just trigger toggle task to revert the pin back to low level. You can always read the pin level to ensure you don't invert the level on the pin before calling toggle task.

    Kenneth

Children
Related