Writing to settings (non-volatile memory) causes GPIO interrupt triggering losses

SDK 2.1.0

nRF9160

Hi,

I recently configured a GPIO input in my project with an associated interrupt whenever it detects a high to low transition. The transition is externally generated every 20ms.

With each interruption, a work is rescheduled.

Everything works as expected until there is a great write (buffer[3500]) to the Settings.

After writing, the work is executed, meaning that the transition was not detected.

It seems to me that it's a problem of priorities...

I wanted to know if it is possible, and how, to change the priority of GPIO interrupts.

Regards,

Ricardo

Parents
  • Hello Ricardo,

    Can you please elaborate a bit on how it is not working? When you perform the flash write to settings, does the GPIO input fail to detect changes when it is written, so that you are loosing events? Is it able to detect interrupts when the flash write is complete? Do you get a delayed event? 

    Can you also please share how you have set up the GPIO interrupt? Some snippets, perhaps?

    Best regards,

    Edvin

  • Hi Edvin,

    I'm sorry for the delay in responding.

    I'll try to explain myself better, but you understand the problem.
    I have a change being generated externally every 20ms on a GPIO port, and every time this change is detected, a work is rescheduled for 25ms.
    While there is no writing to settings, all changes are correctly detected on the GPIO port.
    When there is a write to settings, during the write time, there is no change detected.
    After completing writing in settings, the detection of changes in GPIOs will be detected again.

    My GPIO port is configured like this:

    #define ZERO_CROSSING_NODE DT_NODELABEL(uc_zero_cross)
    
    /* declare a pointer to devicetree node identifier */
    static const struct gpio_dt_spec zero_crossing = GPIO_DT_SPEC_GET(ZERO_CROSSING_NODE, gpios);
    
    /* Defines the callback used to detect a gpio state change */
    static struct gpio_callback zero_crossing_gpio_cb;
    
    /* Work queue used by zero crossing */
    static struct k_work_q *zero_crossing_work_q;
    
    /* Work structure used by zero crossing */
    static struct k_work_delayable zero_crossing_work;
    
    
    ret_code_t
    UC_ZeroCrossing_Init(struct k_work_q *work_q)
    {
    	/* Check for NULL pointers in the arguments */
    	if (!work_q) {
    		return INVALID_ARGUMENT;
    	} 
    	
    	/* Initialise control variables */
    	int configure_gpio_result = NRF_SUCCESS;
    
        /* Check if device is ready */
        if (!device_is_ready(zero_crossing.port)) {
            LOG_ERR("Zero Crossing GPIO device not ready");
            return ERROR;
        }
        /* Configure gpio port */
        configure_gpio_result = gpio_pin_configure_dt(&zero_crossing, GPIO_INPUT);
        if (NRF_SUCCESS != configure_gpio_result) {
            LOG_ERR("Failed to configure Zero Crossing GPIO pin (%d)", configure_gpio_result);
            return ERROR;
        }
        configure_gpio_result = gpio_pin_interrupt_configure_dt(&zero_crossing, GPIO_INT_EDGE_TO_INACTIVE);
        if (NRF_SUCCESS != configure_gpio_result) {
            LOG_ERR("Failed to configure Zero Crossing GPIO pin (%d)", configure_gpio_result);
            return ERROR;
        }
    	/* configure a gpio calback */
        gpio_init_callback(&zero_crossing_gpio_cb, UC_ZeroCrossing_gpio_cb, BIT(zero_crossing.pin));
        gpio_add_callback(zero_crossing.port, &zero_crossing_gpio_cb);
        
    	
    	/* Initialise the kwork structure to report a last gasp */
        UC_Utils_WorkInitDelayable(&zero_crossing_work, UC_ZeroCrossing_LastGasp);
    
        /* Update the work queue used for report a last gasp */
        zero_crossing_work_q = work_q;
    
        LOG_INF("Zero Crossing driver initialised.");
    
        return SUCCESS;
    }
    
    void 
    UC_ZeroCrossing_gpio_cb(const struct device *dev, struct gpio_callback *cb,
                                        uint32_t pins)
    {
    
        LOG_DBG("Zero Cross detected - Reschedule work");
    
        /* Schedule task to report a last gasp */
        int submit_result = k_work_reschedule_for_queue(zero_crossing_work_q, &zero_crossing_work, K_MSEC(ZERO_CROSSING_RESCHEDULE_TIME_MS));
        if (submit_result < NRF_SUCCESS) {
            LOG_ERR("Failed to submit Zero Crossing work to queue (%d)", submit_result);
        }
    }
    
    void 
    UC_ZeroCrossing_LastGasp(struct k_work *work)
    {
        LOG_WRN("Zero Crossing NOT detected.");
        
        /* Trigger a Lasp Gasp */
            zc_callback();
    }

    Log output:

    [00:00:50.504,913] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.524,932] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.544,921] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.564,910] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.584,930] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.604,919] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.624,908] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.644,927] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.664,916] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.673,919] <inf> UC_SETTI: Start Saving JSON script
    [00:00:50.761,016] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.764,984] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.784,912] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.804,565] <inf> UC_SETTI: Saved new JSON script
    [00:00:50.804,901] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.805,480] <wrn> UC_ZCROSS: Zero Crossing NOT detected.
    [00:00:50.824,920] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.844,909] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.864,898] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.884,918] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.904,907] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work

    As you can see from the log time, between 50.664sec and 50.764sec, only one change (50.761sec) was detected in the GPIO port.

    Thanks for the help.


    Regards,
    Ricardo

Reply
  • Hi Edvin,

    I'm sorry for the delay in responding.

    I'll try to explain myself better, but you understand the problem.
    I have a change being generated externally every 20ms on a GPIO port, and every time this change is detected, a work is rescheduled for 25ms.
    While there is no writing to settings, all changes are correctly detected on the GPIO port.
    When there is a write to settings, during the write time, there is no change detected.
    After completing writing in settings, the detection of changes in GPIOs will be detected again.

    My GPIO port is configured like this:

    #define ZERO_CROSSING_NODE DT_NODELABEL(uc_zero_cross)
    
    /* declare a pointer to devicetree node identifier */
    static const struct gpio_dt_spec zero_crossing = GPIO_DT_SPEC_GET(ZERO_CROSSING_NODE, gpios);
    
    /* Defines the callback used to detect a gpio state change */
    static struct gpio_callback zero_crossing_gpio_cb;
    
    /* Work queue used by zero crossing */
    static struct k_work_q *zero_crossing_work_q;
    
    /* Work structure used by zero crossing */
    static struct k_work_delayable zero_crossing_work;
    
    
    ret_code_t
    UC_ZeroCrossing_Init(struct k_work_q *work_q)
    {
    	/* Check for NULL pointers in the arguments */
    	if (!work_q) {
    		return INVALID_ARGUMENT;
    	} 
    	
    	/* Initialise control variables */
    	int configure_gpio_result = NRF_SUCCESS;
    
        /* Check if device is ready */
        if (!device_is_ready(zero_crossing.port)) {
            LOG_ERR("Zero Crossing GPIO device not ready");
            return ERROR;
        }
        /* Configure gpio port */
        configure_gpio_result = gpio_pin_configure_dt(&zero_crossing, GPIO_INPUT);
        if (NRF_SUCCESS != configure_gpio_result) {
            LOG_ERR("Failed to configure Zero Crossing GPIO pin (%d)", configure_gpio_result);
            return ERROR;
        }
        configure_gpio_result = gpio_pin_interrupt_configure_dt(&zero_crossing, GPIO_INT_EDGE_TO_INACTIVE);
        if (NRF_SUCCESS != configure_gpio_result) {
            LOG_ERR("Failed to configure Zero Crossing GPIO pin (%d)", configure_gpio_result);
            return ERROR;
        }
    	/* configure a gpio calback */
        gpio_init_callback(&zero_crossing_gpio_cb, UC_ZeroCrossing_gpio_cb, BIT(zero_crossing.pin));
        gpio_add_callback(zero_crossing.port, &zero_crossing_gpio_cb);
        
    	
    	/* Initialise the kwork structure to report a last gasp */
        UC_Utils_WorkInitDelayable(&zero_crossing_work, UC_ZeroCrossing_LastGasp);
    
        /* Update the work queue used for report a last gasp */
        zero_crossing_work_q = work_q;
    
        LOG_INF("Zero Crossing driver initialised.");
    
        return SUCCESS;
    }
    
    void 
    UC_ZeroCrossing_gpio_cb(const struct device *dev, struct gpio_callback *cb,
                                        uint32_t pins)
    {
    
        LOG_DBG("Zero Cross detected - Reschedule work");
    
        /* Schedule task to report a last gasp */
        int submit_result = k_work_reschedule_for_queue(zero_crossing_work_q, &zero_crossing_work, K_MSEC(ZERO_CROSSING_RESCHEDULE_TIME_MS));
        if (submit_result < NRF_SUCCESS) {
            LOG_ERR("Failed to submit Zero Crossing work to queue (%d)", submit_result);
        }
    }
    
    void 
    UC_ZeroCrossing_LastGasp(struct k_work *work)
    {
        LOG_WRN("Zero Crossing NOT detected.");
        
        /* Trigger a Lasp Gasp */
            zc_callback();
    }

    Log output:

    [00:00:50.504,913] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.524,932] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.544,921] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.564,910] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.584,930] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.604,919] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.624,908] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.644,927] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.664,916] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.673,919] <inf> UC_SETTI: Start Saving JSON script
    [00:00:50.761,016] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.764,984] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.784,912] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.804,565] <inf> UC_SETTI: Saved new JSON script
    [00:00:50.804,901] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.805,480] <wrn> UC_ZCROSS: Zero Crossing NOT detected.
    [00:00:50.824,920] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.844,909] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.864,898] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.884,918] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
    [00:00:50.904,907] <dbg> UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work

    As you can see from the log time, between 50.664sec and 50.764sec, only one change (50.761sec) was detected in the GPIO port.

    Thanks for the help.


    Regards,
    Ricardo

Children
No Data
Related