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