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

GPIOTE two events for the same pin?

Hello,

For nRF51822 and nRF52832, I'm using GPIOTE, PPI and timers to measure the duration that a pin, which is normally low, goes hi (typically 100-300 milliseconds). I don't want to use GPIOTE_CONFIG_POLARITY_Toggle because I'd have to keep track of which edge in the interrupt routine. So I'd like to use GPIOTE to watch for both GPIOTE_CONFIG_POLARITY_LoToHi and GPIOTE_CONFIG_POLARITY_HiToLo on the same pin.

This post states that using two GPIOTE events on the same pin breaks the one-pin-one-GPIOTE rule. Here's my code:

void gpiote_ppi_init(void) {

    nrfx_err_t err_code = NRF_SUCCESS;

    // Configure GPIOTE channel 0 as event that occurs when pin changes from digital
    // lo to hi.
    NRF_GPIOTE->CONFIG[0] =  (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos)
                | (SENSOR_PIN << GPIOTE_CONFIG_PSEL_Pos)
                | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
  
    // Configure GPIOTE channel 1 as event that occurs when pin changes from digital
    // hi to lo.
    NRF_GPIOTE->CONFIG[1] =  (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)
                | (RH_PHOTOTRANSISTOR_COMPARATOR_PIN << GPIOTE_CONFIG_PSEL_Pos) // using GPIO photoTransistorDigitalPin as input
                | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
  
    // Interrupt only on hi to low.
    NRF_GPIOTE->INTENCLR = GPIOTE_INTENCLR_IN0_Msk | GPIOTE_INTENCLR_IN2_Msk | GPIOTE_INTENCLR_IN3_Msk;
    NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN1_Msk;
  
    // Clear all events.
    NRF_GPIOTE->EVENTS_IN[0] = 0;
    NRF_GPIOTE->EVENTS_IN[1] = 0;
    NRF_GPIOTE->EVENTS_IN[2] = 0;
    NRF_GPIOTE->EVENTS_IN[3] = 0;
  

    // PPI channels
    uint8_t chan_0 = 255;
    uint8_t chan_1 = 255;
    uint8_t chan_2 = 255;
    uint8_t chan_3 = 255;

    err_code = nrfx_ppi_channel_alloc(&chan_0);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_ppi_channel_alloc(&chan_1);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_ppi_channel_alloc(&chan_2);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_ppi_channel_alloc(&chan_3);
    APP_ERROR_CHECK(err_code);

    // Configure PPI channel 0 to increment TIMER1 when TIMER2 overflows.
    err_code = nrfx_ppi_channel_assign(chan_0, nrfx_timer_event_address_get(&m_timer2,NRF_TIMER_EVENT_COMPARE0), nrfx_timer_task_address_get(&m_timer1,NRF_TIMER_TASK_COUNT));
    APP_ERROR_CHECK(err_code);

    // Configure PPI channel 1 to start TIMER2 when GPIOTE channel 0 event occurs.
    err_code = nrfx_ppi_channel_assign(chan_1, (uint32_t)&NRF_GPIOTE->EVENTS_IN[0],nrfx_timer_task_address_get(&m_timer2,NRF_TIMER_TASK_START));
    APP_ERROR_CHECK(err_code);

    // Configure PPI channel 2 to capture TIMER1 when GPIOTE channel 1 event occurs.
    err_code = nrfx_ppi_channel_assign(chan_2, (uint32_t)&NRF_GPIOTE->EVENTS_IN[1],nrfx_timer_task_address_get(&m_timer2,NRF_TIMER_TASK_CAPTURE0));
    APP_ERROR_CHECK(err_code);

    // Configure PPI channel 3 to capture TIMER2 when GPIOTE channel 1 event occurs.
    err_code = nrfx_ppi_channel_assign(chan_3, (uint32_t)&NRF_GPIOTE->EVENTS_IN[1],nrfx_timer_task_address_get(&m_timer1,NRF_TIMER_TASK_CAPTURE0));
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_ppi_channel_enable(chan_0);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_ppi_channel_enable(chan_1);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_ppi_channel_enable(chan_2);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_ppi_channel_enable(chan_3);
    APP_ERROR_CHECK(err_code);

}

So far I've not noticed any issues and wanted to be assured that we won't experience any problems. Is this safe for production?

When we revise our board next, should I be connecting our sensor to two GPIO pins and use one pin to watch for LoToHi and the other for HiToLo?

Many thanks,

Tim

Parents Reply Children
No Data
Related