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
  • Hi again Tim

    Yes, as Susheel and RK are saying in that post, this is breaking the "one-pin-one GPIOTE" rule, so we can't recommend it or guarantee that it will work. If you do sufficient testing and feel confident that this does work for you, you're of course, welcome to do what works for you, but it's not recommended by Nordic. My suggestion would be to use one pin for each GPIOTE event/task.

    Best regards,

    Simon

  • Thanks Simonr. I will modify our circuit for nRF52832 product in development to use two IO pins. I'm wondering, though, about nRF51822 product we have in the field, which uses the same code as above. Susheel says:

    +1 for RK, It does break the rule, could be some side effects if myPin is toggling close to system clock frequency. But at lower frequencies on myPin (<4MhZ) this would work (not recommended though)

    For my product, the pin input signal (from a sensor) is not modulated at a certain frequency. I'm using GPIOTE to act on a single pulse (one LoToHi followed usually 100-300 ms later by one HiToLo, then some time later, repeat). Given what Susheel says above, am I safe? I posed this question a while ago and Hakon's response suggested it should be okay.

    If not, is there anything I can do to resolve? I'd rather not use toggle event because sometimes a pulse can come quickly after the previous one (it can be quite random), and with SoftDevice enabled, the interrupt handler might not fire in time to flip the event.

    If given our use case this is an issue for nRF51822, I'm hopeful for a workaround that we can push out to our customers via OTA DFU.

    Many thanks,

    -Tim

Reply
  • Thanks Simonr. I will modify our circuit for nRF52832 product in development to use two IO pins. I'm wondering, though, about nRF51822 product we have in the field, which uses the same code as above. Susheel says:

    +1 for RK, It does break the rule, could be some side effects if myPin is toggling close to system clock frequency. But at lower frequencies on myPin (<4MhZ) this would work (not recommended though)

    For my product, the pin input signal (from a sensor) is not modulated at a certain frequency. I'm using GPIOTE to act on a single pulse (one LoToHi followed usually 100-300 ms later by one HiToLo, then some time later, repeat). Given what Susheel says above, am I safe? I posed this question a while ago and Hakon's response suggested it should be okay.

    If not, is there anything I can do to resolve? I'd rather not use toggle event because sometimes a pulse can come quickly after the previous one (it can be quite random), and with SoftDevice enabled, the interrupt handler might not fire in time to flip the event.

    If given our use case this is an issue for nRF51822, I'm hopeful for a workaround that we can push out to our customers via OTA DFU.

    Many thanks,

    -Tim

Children
No Data
Related