<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Writing to settings (non-volatile memory) causes GPIO interrupt triggering losses</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/116960/writing-to-settings-non-volatile-memory-causes-gpio-interrupt-triggering-losses</link><description>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</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Wed, 11 Dec 2024 11:19:25 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/116960/writing-to-settings-non-volatile-memory-causes-gpio-interrupt-triggering-losses" /><item><title>RE: Writing to settings (non-volatile memory) causes GPIO interrupt triggering losses</title><link>https://devzone.nordicsemi.com/thread/514477?ContentTypeID=1</link><pubDate>Wed, 11 Dec 2024 11:19:25 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:07dcc47c-c2d5-4dd2-a730-d746b5f4d604</guid><dc:creator>RicardoCarvalho</dc:creator><description>&lt;p&gt;Hi Edvin,&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
[quote userid="26071" url="~/f/nordic-q-a/116960/writing-to-settings-non-volatile-memory-causes-gpio-interrupt-triggering-losses/514439"]Whenever you get a GPIO interrupt, it will be sent to your application[/quote]
&lt;p&gt;I don&amp;#39;t send it whenever I receive an interruption, on the contrary, I&amp;#39;m interested in detecting the lack of interruptions, whenever I receive a GPIO interruption I reschedule a work for 25msec (it waits for the next interruption), in the absence of an interruption the work is executed and then it reports the failure to the application.&lt;/p&gt;
&lt;p&gt;What it seems to me is happening is that because writing to flash takes more than 25msec, when it finishes, the work is queued and executed, reporting a false lack of interrupt to the application.&lt;/p&gt;
&lt;p&gt;That&amp;#39;s why I said that the best solution would be to cancel the work before writing...&lt;/p&gt;
&lt;p&gt;Regards,&lt;/p&gt;
&lt;p&gt;Ricardo&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Edit:&lt;br /&gt;I will try something else, I will transfer all settings storage to external flash, this should solve the problem.&lt;/p&gt;
&lt;p&gt;Edit 2:&lt;br /&gt;Just to say that moving settings&amp;nbsp;storage to external flash solves the problem.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to settings (non-volatile memory) causes GPIO interrupt triggering losses</title><link>https://devzone.nordicsemi.com/thread/514439?ContentTypeID=1</link><pubDate>Wed, 11 Dec 2024 08:59:33 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:de8edcc3-396b-43e9-ac11-1db28f521d3a</guid><dc:creator>Edvin</dc:creator><description>&lt;p&gt;I think I understand.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Whenever you get a GPIO interrupt, it will be sent to your application, unless another process is blocking it, which in your case is the flash write. In that case, it will be forwarded to your application once the blocking action is finished.&amp;nbsp;&lt;/p&gt;
[quote user="RicardoCarvalho"]I don&amp;#39;t need to know how many transitions happened, I just need to notify them as soon as possible if one fails.[/quote]
&lt;p&gt;In that case, you will be notified as soon as possible, once the flash write has finished. If it fails twice during the flash write, however, you will only be notified once, because when an interrupt is being handled, it is also cleared. If an interrupt happens twice before you handle it, it doesn&amp;#39;t stack, so you will only know that it happens once.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;So as I mentioned, it is possbile to set up a counter using the DPPI (a peripheral used to link up events and tasks in other peripherals). So you could link up the event where the GPIO triggers, to a task in a timer set in counter mode to increment by one. This way you can have an event counter to count the number of events without involving the CPU. Then, you can later in the interrupt handler check how much the timer has incremented to see how many times it happened. However, that is only if you need the amount of times it happened while writing.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Best regards,&lt;/p&gt;
&lt;p&gt;Edvin&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to settings (non-volatile memory) causes GPIO interrupt triggering losses</title><link>https://devzone.nordicsemi.com/thread/514336?ContentTypeID=1</link><pubDate>Tue, 10 Dec 2024 16:11:41 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e6d2a5a3-3483-4a70-b769-cc5bbb1db365</guid><dc:creator>RicardoCarvalho</dc:creator><description>&lt;p&gt;Hi Edvin,&lt;br /&gt;&lt;br /&gt;Thanks for the explanation.&lt;br /&gt;&lt;br /&gt;I thought it could be some error in my implementation, or that it was possible to change the priorities of writing to flash in relation to GPIO interrupts... being a CPU limitation, I have to think of another way.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
[quote userid="26071" url="~/f/nordic-q-a/116960/writing-to-settings-non-volatile-memory-causes-gpio-interrupt-triggering-losses/514159"]What kind of work is it that you are rescheduling on the GPIO interrupt?&amp;nbsp;[/quote]
&lt;p&gt;It&amp;#39;s nothing elaborate, it&amp;#39;s just a calback assigned by lwm2m to notify the failure and imminent shutdown.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
[quote userid="26071" url="~/f/nordic-q-a/116960/writing-to-settings-non-volatile-memory-causes-gpio-interrupt-triggering-losses/514159"]It could be possible to limit the amount you write to flash (but do it more often), so that it doesn&amp;#39;t take 90ms.[/quote]
&lt;p&gt;The write to flash is a single 3500 byte buffer, it&amp;#39;s not easy to split this write, and as you say, it can always match and fail.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
[quote userid="26071" url="~/f/nordic-q-a/116960/writing-to-settings-non-volatile-memory-causes-gpio-interrupt-triggering-losses/514159"]Alternatively, it is possible to do some tricks using DPPI to count the number of cross detections while the flash write operations are ongoing, and then catch up with the work once the flash write operation is done.[/quote]
&lt;p&gt;I don&amp;#39;t need to know how many transitions happened, I just need to notify them as soon as possible if one fails.&lt;br /&gt;&lt;br /&gt;I&amp;#39;m more inclined to, before writing, cancel the scheduled work, at least I won&amp;#39;t get false positives every time I finish writing.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;Regards,&lt;br /&gt;Ricardo&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to settings (non-volatile memory) causes GPIO interrupt triggering losses</title><link>https://devzone.nordicsemi.com/thread/514159?ContentTypeID=1</link><pubDate>Tue, 10 Dec 2024 08:03:45 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:5152c92b-a146-4ccb-8fdd-f18e9a7f4f94</guid><dc:creator>Edvin</dc:creator><description>&lt;p&gt;Ok, I understand. So while you are performing the flash operation, no interrupts are forwarded to your application, and when the write is done, you will get one interrupt (50.761), which is the queued up interrupt, and then it will presume as normal from 50.764 (until the next flash operation).&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;What kind of work is it that you are rescheduling on the GPIO interrupt?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The thing is that when you are performing flash write operations, the CPU is occupied, so it is not possible to do anything else at that point in time.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;How time sensitive is the work you are rescheduling. It could be possible to limit the amount you write to flash (but do it more often), so that it doesn&amp;#39;t take 90ms. But unless you time it to happen directly after a cross detection, it may still block your interrupt from triggering exactly when it occurs. However, if only one interrupt happens while you are writing to flash, this interrupt will be forwarded to the CPU (your application) when the flash write is done.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Alternatively, it is possible to do some tricks using DPPI to count the number of cross detections while the flash write operations are ongoing, and then catch up with the work once the flash write operation is done. Let me know what you think.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Best regards,&lt;/p&gt;
&lt;p&gt;Edvin&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to settings (non-volatile memory) causes GPIO interrupt triggering losses</title><link>https://devzone.nordicsemi.com/thread/514018?ContentTypeID=1</link><pubDate>Mon, 09 Dec 2024 12:42:22 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:1144df1c-2801-496f-b037-b7bf2bb62e27</guid><dc:creator>RicardoCarvalho</dc:creator><description>&lt;p&gt;Hi Edvin,&lt;/p&gt;
&lt;p&gt;I&amp;#39;m sorry for the delay in responding.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ll try to explain myself better, but you understand the problem.&lt;br /&gt;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.&lt;br /&gt;While there is no writing to settings, all changes are correctly detected on the GPIO port.&lt;br /&gt;When there is a write to settings, during the write time, there is no change detected.&lt;br /&gt;After completing writing in settings, the detection of changes in GPIOs will be detected again.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;My GPIO port is configured like this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#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(&amp;quot;Zero Crossing GPIO device not ready&amp;quot;);
        return ERROR;
    }
    /* Configure gpio port */
    configure_gpio_result = gpio_pin_configure_dt(&amp;amp;zero_crossing, GPIO_INPUT);
    if (NRF_SUCCESS != configure_gpio_result) {
        LOG_ERR(&amp;quot;Failed to configure Zero Crossing GPIO pin (%d)&amp;quot;, configure_gpio_result);
        return ERROR;
    }
    configure_gpio_result = gpio_pin_interrupt_configure_dt(&amp;amp;zero_crossing, GPIO_INT_EDGE_TO_INACTIVE);
    if (NRF_SUCCESS != configure_gpio_result) {
        LOG_ERR(&amp;quot;Failed to configure Zero Crossing GPIO pin (%d)&amp;quot;, configure_gpio_result);
        return ERROR;
    }
	/* configure a gpio calback */
    gpio_init_callback(&amp;amp;zero_crossing_gpio_cb, UC_ZeroCrossing_gpio_cb, BIT(zero_crossing.pin));
    gpio_add_callback(zero_crossing.port, &amp;amp;zero_crossing_gpio_cb);
    
	
	/* Initialise the kwork structure to report a last gasp */
    UC_Utils_WorkInitDelayable(&amp;amp;zero_crossing_work, UC_ZeroCrossing_LastGasp);

    /* Update the work queue used for report a last gasp */
    zero_crossing_work_q = work_q;

    LOG_INF(&amp;quot;Zero Crossing driver initialised.&amp;quot;);

    return SUCCESS;
}

void 
UC_ZeroCrossing_gpio_cb(const struct device *dev, struct gpio_callback *cb,
                                    uint32_t pins)
{

    LOG_DBG(&amp;quot;Zero Cross detected - Reschedule work&amp;quot;);

    /* Schedule task to report a last gasp */
    int submit_result = k_work_reschedule_for_queue(zero_crossing_work_q, &amp;amp;zero_crossing_work, K_MSEC(ZERO_CROSSING_RESCHEDULE_TIME_MS));
    if (submit_result &amp;lt; NRF_SUCCESS) {
        LOG_ERR(&amp;quot;Failed to submit Zero Crossing work to queue (%d)&amp;quot;, submit_result);
    }
}

void 
UC_ZeroCrossing_LastGasp(struct k_work *work)
{
    LOG_WRN(&amp;quot;Zero Crossing NOT detected.&amp;quot;);
    
    /* Trigger a Lasp Gasp */
        zc_callback();
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Log output:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;[00:00:50.504,913] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.524,932] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.544,921] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.564,910] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.584,930] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.604,919] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.624,908] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.644,927] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.664,916] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.673,919] &amp;lt;inf&amp;gt; UC_SETTI: Start Saving JSON script
[00:00:50.761,016] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.764,984] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.784,912] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.804,565] &amp;lt;inf&amp;gt; UC_SETTI: Saved new JSON script
[00:00:50.804,901] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.805,480] &amp;lt;wrn&amp;gt; UC_ZCROSS: Zero Crossing NOT detected.
[00:00:50.824,920] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.844,909] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.864,898] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.884,918] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work
[00:00:50.904,907] &amp;lt;dbg&amp;gt; UC_ZCROSS: UC_ZeroCrossing_gpio_cb: Zero Cross detected - Reschedule work&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;Thanks for the help.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;Regards,&lt;br /&gt;Ricardo&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to settings (non-volatile memory) causes GPIO interrupt triggering losses</title><link>https://devzone.nordicsemi.com/thread/513516?ContentTypeID=1</link><pubDate>Wed, 04 Dec 2024 21:42:11 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:29806713-aeef-49b4-9b40-8981facfacca</guid><dc:creator>Edvin</dc:creator><description>&lt;p&gt;Hello Ricardo,&lt;/p&gt;
&lt;p&gt;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?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Can you also please share how you have set up the GPIO interrupt? Some snippets, perhaps?&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Best regards,&lt;/p&gt;
&lt;p&gt;Edvin&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>