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

GPIOTE EVENT CLEAR

nrf52832, keil with startups from sdk13

Initialization:

    /* Start 32 MHz crystal oscillator */
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_HFCLKSTART    = 1;

    /* Wait for the external oscillator to start up */
    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
    {
        // Do nothing.
    }
    
/****************************************************************************************/  
    /* Configure Timer0 */   
    NRF_TIMER0->PRESCALER = 0;
    NRF_TIMER0->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
    NRF_TIMER0->MODE = TIMER_MODE_MODE_Timer;    
    
    /* Configure GPIO PIN_NUM */
    NRF_GPIO->PIN_CNF[PIN_NUM1] = (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
                                 (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
                                 (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
                                 (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
                                 (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
    
    /* Configure GPIOTE 0*/
    NRF_GPIOTE->CONFIG[0] |= (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | 
                             (PIN_NUM1 << GPIOTE_CONFIG_PSEL_Pos) |
                             (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);
    NRF_GPIOTE->INTENSET |= GPIOTE_INTENSET_IN0_Enabled << GPIOTE_INTENSET_IN0_Pos;
    
    /* Configure PPI 0*/
    NRF_PPI->CH[0].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0];
    NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TIMER0->TASKS_CAPTURE[0];
    NRF_PPI->FORK[0].TEP = (uint32_t)&NRF_TIMER0->TASKS_CLEAR;
    NRF_PPI->CHENSET |= PPI_CHENSET_CH0_Enabled << PPI_CHENSET_CH0_Pos;
/****************************************************************************************/

    NRF_TIMER0->TASKS_START = 1;
    NVIC_EnableIRQ(GPIOTE_IRQn);

IntHandler:

void GPIOTE_IRQHandler(void)
{
    if (1 == NRF_GPIOTE->EVENTS_IN[0])
    {
        time1 = NRF_TIMER0->CC[0];
        switch (state1)
        {
        ...
        }
        NRF_GPIOTE->EVENTS_IN[0] = 0;
    }
}

With one event everything working well. Then I add another:

    /* Start 32 MHz crystal oscillator */
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_HFCLKSTART    = 1;

    /* Wait for the external oscillator to start up */
    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
    {
        // Do nothing.
    }
    
/****************************************************************************************/   
    /* Configure Timer0 */   
    NRF_TIMER0->PRESCALER = 0;
    NRF_TIMER0->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
    NRF_TIMER0->MODE = TIMER_MODE_MODE_Timer;    
    
    /* Configure GPIO PIN_NUM */
    NRF_GPIO->PIN_CNF[PIN_NUM1] = (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
                                 (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
                                 (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
                                 (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
                                 (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
    
    /* Configure GPIOTE 0*/
    NRF_GPIOTE->CONFIG[0] |= (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | 
                             (PIN_NUM1 << GPIOTE_CONFIG_PSEL_Pos) |
                             (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);
    NRF_GPIOTE->INTENSET |= GPIOTE_INTENSET_IN0_Enabled << GPIOTE_INTENSET_IN0_Pos;
    
    /* Configure PPI 0*/
    NRF_PPI->CH[0].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0];
    NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TIMER0->TASKS_CAPTURE[0];
    NRF_PPI->FORK[0].TEP = (uint32_t)&NRF_TIMER0->TASKS_CLEAR;
    NRF_PPI->CHENSET |= PPI_CHENSET_CH0_Enabled << PPI_CHENSET_CH0_Pos;
/****************************************************************************************/

/****************************************************************************************/     
    /* Configure Timer1 */   
    NRF_TIMER1->PRESCALER = 0;
    NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
    NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;    
    
    /* Configure GPIO PIN_NUM */
    NRF_GPIO->PIN_CNF[PIN_NUM2] = (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
                                 (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
                                 (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
                                 (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
                                 (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
    
    /* Configure GPIOTE 1*/
    NRF_GPIOTE->CONFIG[1] |= (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | 
                             (PIN_NUM2 << GPIOTE_CONFIG_PSEL_Pos) |
                             (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);
    NRF_GPIOTE->INTENSET |= GPIOTE_INTENSET_IN1_Enabled << GPIOTE_INTENSET_IN1_Pos;
    
    /* Configure PPI 1*/
    NRF_PPI->CH[1].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[1];
    NRF_PPI->CH[1].TEP = (uint32_t)&NRF_TIMER1->TASKS_CAPTURE[0];
    NRF_PPI->FORK[1].TEP = (uint32_t)&NRF_TIMER1->TASKS_CLEAR;
    NRF_PPI->CHENSET |= PPI_CHENSET_CH1_Enabled << PPI_CHENSET_CH1_Pos;
/****************************************************************************************/    



    NRF_TIMER0->TASKS_START = 1;
    NRF_TIMER1->TASKS_START = 1;
    NVIC_EnableIRQ(GPIOTE_IRQn);

void GPIOTE_IRQHandler(void)
{
    if (1 == NRF_GPIOTE->EVENTS_IN[0])
    {
        time1 = NRF_TIMER0->CC[0];
        switch (state1)
        {
        ...
        }
        NRF_GPIOTE->EVENTS_IN[0] = 0;
    }
    if (1 == NRF_GPIOTE->EVENTS_IN[1])
    {
        time2 = NRF_TIMER0->CC[1];
        switch (state2)
        {
        ...
        }
        NRF_GPIOTE->EVENTS_IN[1] = 0;
    }
}

I need to measure SENT signal from two channels, minimal signal lenght is 36 uSec, and with two channels sometimes I have 0 in time1/time2 (they are global) vars. I think this because when I for example handled first channel, EVENT_IN[0] didn't be cleared (I didn't see clearing in System Viewer, after NRF_GPIOTE->EVENTS_IN[0] = 0; it is still 1 in System Viewer). And when second channel generate EVENT_IN[1] I came into if (1 == NRF_GPIOTE->EVENTS_IN[0]), but I shouldn't.

Is it real? How to clear event correctly?

  • For greater clarity I made project in SES:

    #include <stdint.h>
    #include "nrf.h"
    
    #define PIN_NUM1 16
    #define PIN_NUM2 18
    
    uint32_t sent1Time = 0;
    uint32_t sent2Time = 0;
    
    uint32_t sent1Errors = 0;
    uint32_t sent2Errors = 0;
    
    void GPIOTE_IRQHandler(void)
    {
        if (1 == NRF_GPIOTE->EVENTS_IN[0])
        {
            sent1Time = NRF_TIMER0->CC[0];
            if (0 == sent1Time)
            {
                ++sent1Errors;
            }
            NRF_GPIOTE->EVENTS_IN[0] = 0;
        }
        
        if (1 == NRF_GPIOTE->EVENTS_IN[1])
        {
            sent2Time = NRF_TIMER1->CC[0];
            if (0 == sent2Time)
            {
                ++sent2Errors;
            }
            NRF_GPIOTE->EVENTS_IN[1] = 0;
        }
    }
    
    int main()
    {
        /* Start 32 MHz crystal oscillator */
        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_HFCLKSTART    = 1;
    
        /* Wait for the external oscillator to start up */
        while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
        {
            // Do nothing.
        }
        
    /***************************************SENT1 INIT***************************************/  
        /* Configure Timer0 */   
        NRF_TIMER0->PRESCALER = 0;
        NRF_TIMER0->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
        NRF_TIMER0->MODE = TIMER_MODE_MODE_Timer;    
        
        /* Configure GPIO PIN_NUM */
        NRF_GPIO->PIN_CNF[PIN_NUM1] = (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
                                     (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
                                     (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
                                     (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
                                     (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
        
        /* Configure GPIOTE 0*/
        NRF_GPIOTE->CONFIG[0] |= (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | 
                                 (PIN_NUM1 << GPIOTE_CONFIG_PSEL_Pos) |
                                 (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);
        NRF_GPIOTE->INTENSET |= GPIOTE_INTENSET_IN0_Enabled << GPIOTE_INTENSET_IN0_Pos;
        
        /* Configure PPI 0*/
        NRF_PPI->CH[0].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0];
        NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TIMER0->TASKS_CAPTURE[0];
        NRF_PPI->FORK[0].TEP = (uint32_t)&NRF_TIMER0->TASKS_CLEAR;
        NRF_PPI->CHENSET |= PPI_CHENSET_CH0_Enabled << PPI_CHENSET_CH0_Pos;
    /****************************************************************************************/
    
    /***************************************SENT2 INIT***************************************/    
    //    /* Configure Timer1 */   
    //    NRF_TIMER1->PRESCALER = 0;
    //    NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
    //    NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;    
    //    
    //    /* Configure GPIO PIN_NUM */
    //    NRF_GPIO->PIN_CNF[PIN_NUM2] = (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
    //                                 (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
    //                                 (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
    //                                 (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
    //                                 (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
    //    
    //    /* Configure GPIOTE 1*/
    //    NRF_GPIOTE->CONFIG[1] |= (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | 
    //                             (PIN_NUM2 << GPIOTE_CONFIG_PSEL_Pos) |
    //                             (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);
    //    NRF_GPIOTE->INTENSET |= GPIOTE_INTENSET_IN1_Enabled << GPIOTE_INTENSET_IN1_Pos;
    //    
    //    /* Configure PPI 1*/
    //    NRF_PPI->CH[1].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[1];
    //    NRF_PPI->CH[1].TEP = (uint32_t)&NRF_TIMER1->TASKS_CAPTURE[0];
    //    NRF_PPI->FORK[1].TEP = (uint32_t)&NRF_TIMER1->TASKS_CLEAR;
    //    NRF_PPI->CHENSET |= PPI_CHENSET_CH1_Enabled << PPI_CHENSET_CH1_Pos;
    /****************************************************************************************/    
    
        NRF_TIMER0->TASKS_START = 1;
        NRF_TIMER1->TASKS_START = 1;
        NVIC_EnableIRQ(GPIOTE_IRQn);   
        
        while(1)
        {
           // Do nothing;
        }
    }
    

    With commented sent1 or sent2 init section there are not zero values (errors). With both init uncommented, zero values appear on 1 or 2 event randomly.

  • Hey,

    Are you sure that EVENT_IN[0] has not been set back to 1 right after you cleared it. Do you have any control of when the events are triggered? Maybe you can use nrf log to print the value of EVENT_IN right after you have cleared it to make sure it has been cleared.

  • The action is very quick if I write:

    void GPIOTE_IRQHandler(void)
    {
        if (1 == NRF_GPIOTE->EVENTS_IN[0])
        {
            sent1Time = NRF_TIMER0->CC[0];
            if (0 == sent1Time)
            {
                ++sent1Errors;
            }
            NRF_GPIOTE->EVENTS_IN[0] = 0;
            sprintf(rtt_buf, "%s %x\n", "sent1", NRF_GPIOTE->EVENTS_IN[0]);
            SEGGER_RTT_Write(0, rtt_buf, 16);
        }
        
        if (1 == NRF_GPIOTE->EVENTS_IN[1])
        {
            sent2Time = NRF_TIMER1->CC[0];
            if (0 == sent2Time)
            {
                ++sent2Errors;
                SEGGER_RTT_WriteString(0, "sent2 error\n");
            }
            NRF_GPIOTE->EVENTS_IN[1] = 0;
            sprintf(rtt_buf, "%s %x\n", "sent2", NRF_GPIOTE->EVENTS_IN[1]);
            SEGGER_RTT_Write(0, rtt_buf, 16);
        }
    }

    I get:

    <spoiler>sent2 0
    sent2 0
    sent1 0
    sent2 0
    sent1 0
    sent1 0
    sent1 0
    sent2 0
    sent2 0
    sent2 0
    sent1 0
    sent1 0
    sent1 0
    sent1 0
    sent2 0
    sent2 0
    sent2 0
    sent1 0
    sent1 0
    sent1 0
    sent2 0
    sent2 0
    sent2 0
    sent1 0
    sent1 0
    sent2 0
    sent1 0
    sent2 0
    sent1 0
    sent1 0
    sent1 0
    sent2 0
    sent2 0
    sent1 0
    sent2 0
    sent1 0
    sent1 0
    sent2 0
    sent1 0
    sent1 0
    sent2 0
    sent2 0
    sent1 0
    sent1 0
    sent1 0
    sent2 0
    sent1 0
    sent2 0
    sent2 0
    sent2 0
    sent2 0
    sent2 0
    sent1 0
    sent1 0
    sent2 0
    sent2 0
    sent2 0
    sent1 0
    sent1 0
    sent2 0
    sent1 0
    sent2 0
    sent1 0
    sent1 0
    sent2 0
    sent1 0
    sent2 0
    sent1 0
    sent1 0
    sent2 0
    sent2 0
    sent2 0
    sent1 0
    sent1 0
    sent1 0
    sent2 0
    sent1 0
    sent2 0
    sent2 0
    sent2 0
    sent2 0
    sent1 0
    sent2 0
    sent1 0
    sent2 0
    sent1 0
    sent2 0
    sent2 0
    sent1 0
    sent2 0
    sent2 0
    sent2 0
    sent1 0
    sent1 0
    sent2 0
    sent2 0
    sent1 0
    sent1 0
    sent1 0
    sent1 0
    sent2 0
    sent1 0
    sent1 0
    sent1 0
    sent2 0
    sent1 0
    sent1 0
    sent1 0
    sent1 0
    sent2 0
    sent1 0
    sent2 0
    sent1 0
    sent2 0
    sent2 0
    sent2 0
    sent1 0
    sent2 0
    sent1 0
    sent2 0
    sent2 0
    sent1 0
    sent2 0
    sent2 0
    sent2 0
    sent1 0
    sent2 0
    sent2 0
    sent2 0
    sent2 0
    sent1 0
    sent2 0
    sent2 0
    sent1 0
    sent2 0
    sent2 0
    sent2 0
    sent2 0
    sent2 0
    sent1 0
    sent2 0
    sent2 0
    sent1 0
    sent2 0
    sent1 0
    sent2 0
    sent1 0
    sent1 0
    sent1 0
    sent2 0
    sent1 0
    sent1 0
    sent2 0</spoiler>

    with no order.

    If I write:

    void GPIOTE_IRQHandler(void)
    {
        if (1 == NRF_GPIOTE->EVENTS_IN[0])
        {
            sent1Time = NRF_TIMER0->CC[0];
            if (0 == sent1Time)
            {
                ++sent1Errors;
            }
            sprintf(rtt_buf, "%s %x\n", "sent1", NRF_GPIOTE->EVENTS_IN[0]);
            SEGGER_RTT_Write(0, rtt_buf, 16);
            NRF_GPIOTE->EVENTS_IN[0] = 0;
            sprintf(rtt_buf, "%s %x\n", "sent1", NRF_GPIOTE->EVENTS_IN[0]);
            SEGGER_RTT_Write(0, rtt_buf, 16);
        }
        
        if (1 == NRF_GPIOTE->EVENTS_IN[1])
        {
            sent2Time = NRF_TIMER1->CC[0];
            if (0 == sent2Time)
            {
                ++sent2Errors;
                SEGGER_RTT_WriteString(0, "sent2 error\n");
            }
            sprintf(rtt_buf, "%s %x\n", "sent2", NRF_GPIOTE->EVENTS_IN[1]);
            SEGGER_RTT_Write(0, rtt_buf, 16);
            NRF_GPIOTE->EVENTS_IN[1] = 0;
            sprintf(rtt_buf, "%s %x\n", "sent2", NRF_GPIOTE->EVENTS_IN[1]);
            SEGGER_RTT_Write(0, rtt_buf, 16);
        }
    }

    I get something like:

    <spoiler>

    sent1 1
    sent2 0
    sent2 1
    sent1 1
    sent1 1
    sent1 1
    sent2 1
    sent1 1
    sent1 1
    sent2 0
    sent2 0
    sent1 1
    sent1 1
    sent2 1
    sent2 1
    sent1 1
    sent1 1
    sent2 1
    sent2 1
    sent1 1
    sent1 1
    sent2 1
    sent2 1
    sent2 0
    sent2 0
    sent2 1
    sent1 0
    sent2 1
    sent1 1
    sent1 1
    sent1 0
    sent1 0
    sent2 1
    sent2 0
    sent1 1
    sent1 0
    sent2 1
    sent2 1
    sent1 0
    sent1 1
    sent1 0
    sent1 1
    sent2 1
    sent2 0
    sent2 1
    sent2 1
    sent1 1
    sent1 0
    sent2 1
    sent2 1
    sent1 0
    sent1 0
    sent1 1
    sent1 1
    sent2 1
    sent1 1
    sent1 1
    sent1 1
    sent1 0
    sent2 1
    sent1 1
    sent2 0
    sent2 1
    sent2 1
    sent2 0
    sent1 0
    sent1 1
    sent1 0
    sent1 0
    sent1 1
    sent1 1
    sent2 1

    </spoiler>

    also without any order.

    As I think, debugger isn't quick enough.

    Another question is:

    If I configure GPIOTE event from Hi to Low, NRF_GPIOTE->EVENTS_IN[0] will be triggered on Hi to Low edge, or it can be triggered again on Low level when it didn't get back to Hi level?

  • Try using NRF_LOG_FLUSH() and see if it makes a difference.

     

    ArtG89 said:
    If I configure GPIOTE event from Hi to Low, NRF_GPIOTE->EVENTS_IN[0] will be triggered on Hi to Low edge, or it can be triggered again on Low level when it didn't get back to Hi level?

     I believe this part from the documentation should answer your question,

    "An event can be generated in each GPIOTE channel from one of the following input conditions:

    • Rising edge
    • Falling edge
    • Any change"
Related