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