<?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>NRF_GPIOTE EVENTS_PORT woes (again)</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/92708/nrf_gpiote-events_port-woes-again</link><description>I have my own code for handling pin interrupts using the NRF_GPIOTE EVENTS_PORT interrupt. I had some issues with this years ago when I was using the nRF52832 chip, which only has one port. The nRF52833 has two ports and I have interrupts on pins in both</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 13 Oct 2022 19:03:45 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/92708/nrf_gpiote-events_port-woes-again" /><item><title>RE: NRF_GPIOTE EVENTS_PORT woes (again)</title><link>https://devzone.nordicsemi.com/thread/390705?ContentTypeID=1</link><pubDate>Thu, 13 Oct 2022 19:03:45 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:58c18339-7e46-45ce-a786-fb257dbd4a9a</guid><dc:creator>jsheaney</dc:creator><description>&lt;p&gt;After thrashing this over and over, it seems like the worst case scenario (looking at the actual driver and its order of operations) is that a P0 bit gets set after checking it, but before checking P1. That&amp;#39;s the only race condition where it looks like both LATCH registers are clear, but they really are not. In that case, you will exit the ISR, but then the ISR will be immediately re-entered with the P0 bit still set because EVENTS_PORT has already been cleared and set again and the interrupt bit will be pending.&lt;/p&gt;
&lt;p&gt;OK, I believe it! Thanks for your patience!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: NRF_GPIOTE EVENTS_PORT woes (again)</title><link>https://devzone.nordicsemi.com/thread/390571?ContentTypeID=1</link><pubDate>Thu, 13 Oct 2022 08:40:22 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:9e533619-28c6-4d51-8101-af9cc0faa7db</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
[quote user="jsheaney"]At the start of your reply, there is an implication that there are two DETECT signals; on per port. At the end, you quote the GPIOTE text, which sounds like there is only one DETECT signal.[/quote]
&lt;p&gt;I can understand this is not straight forward, but in short you may say that the two DETECT signals that can be generated from Port0 and Port1 is OR&amp;#39;ed together before input to the GPIOTE module, the GPIOTE module will generate the PORT EVENT when this OR&amp;#39;ed DETECT signal go from low to high. It is also worth mentioning that when configuring to use LDTECT to generate the DETECT signal(s), then there is also some additional&amp;nbsp;circuitry between the OR&amp;#39;gate and the GPIOTE module that is used to trigger a DETECT signal in the following corner case condition: &amp;quot;&lt;span&gt;If one or more bits in the LATCH register are 1 after the CPU has performed a clear operation on the LATCH register, a rising edge will be generated on the LDETECT signal.&lt;/span&gt;&amp;quot;&lt;/p&gt;
[quote user="jsheaney"]So if P0-&amp;gt;LATCH has a bit set and P1-&amp;gt;LATCH has a bit set then both have to be cleared in the one ISR. In this scenario, if I clear the bit in P0-&amp;gt;LATCH will a new event be generated, even though I haven&amp;#39;t cleared P1-&amp;gt;LATCH, yet?[/quote]
&lt;p&gt;No.&lt;/p&gt;
[quote user="jsheaney"]If so, that means my ISR is going to be re-entered before I service the P1 bits.[/quote]
&lt;p&gt;This will never happen, an interrupt will never be interrupted by itself. What can happen is that the PORT event is triggered again during&amp;nbsp; execution of the GPIOTE handler, in which case the interrupt will be pending and thereby run again afterwards (presuming of course that you cleared the port event BEFORE you started clearing the LATCH registers, and not the other way around).&lt;/p&gt;
[quote user="jsheaney"]If not, then there&amp;#39;s a race condition getting both LATCH registers clear.[/quote]
&lt;p&gt;There is a possible race condition here, but it can be solved. You just need to ensure that&amp;nbsp;both LATCH registers are 0 the last time you read them by the MCU in the GPIOTE handler. Yes it is possible that they are set after you have read them, but that is not a problem (let me try to explain why). By doing it this way you know that the DETECT signal must have been low at some point (since both LATCH registers were 0), even if it could have changed since you read them. The fact that they&amp;nbsp;both have been 0 at the same time means that any changes afterwards have triggered the DETECT signal and thereby the PORT event (allowing a second GPIOTE handler to be pending).&lt;/p&gt;
&lt;p&gt;What you should &lt;strong&gt;_not_&lt;/strong&gt; do: &amp;quot;Enter GPIOTE handler. Read and clear Port event if set. Read P0-&amp;gt;LATCH, and possible clear it if it&amp;#39;s set. &lt;span style="color:rgba(255, 0, 0, 1);"&gt;Then you read the P1-&amp;gt;LATCH, you find it&amp;#39;s set and you clear it. Then exit the GPIOTE handler.&amp;quot;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In the above case the problem is the &lt;span style="color:rgba(255, 0, 0, 1);"&gt;red&lt;/span&gt; text, because there is a chance that you will miss any change to P0-&amp;gt;LATCH this way. Instead you need to change it to something like this:&lt;/p&gt;
&lt;p&gt;&lt;span&gt;What you should&amp;nbsp;&lt;/span&gt;&lt;span&gt;do: &amp;quot;Enter GPIOTE handler. Read and clear Port event if set. (*)Read P0-&amp;gt;LATCH&lt;/span&gt;&lt;span&gt;, and clear it if it&amp;#39;s set&lt;/span&gt;&lt;span&gt;.&lt;span style="color:rgba(0, 0, 0, 1);"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Then you read the P1-&amp;gt;LATCH, you find it&amp;#39;s set and you clear it. &lt;span style="color:rgba(0, 255, 0, 1);"&gt;Read both P0-&amp;gt;LATCH and P1-&amp;gt;LATCH and check they are both 0, if not repeat from (*).&lt;/span&gt; Then exit the GPIOTE handler.&amp;quot;&lt;/p&gt;
&lt;p&gt;Best regards,&lt;br /&gt;Kenneth&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: NRF_GPIOTE EVENTS_PORT woes (again)</title><link>https://devzone.nordicsemi.com/thread/390517?ContentTypeID=1</link><pubDate>Wed, 12 Oct 2022 19:05:51 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:eb1eaf84-5e0e-4e94-bc7f-670dcea45e1b</guid><dc:creator>jsheaney</dc:creator><description>&lt;p&gt;That link doesn&amp;#39;t work for me and I haven&amp;#39;t been able to do a web search that leads me to that text you quoted. I&amp;#39;m looking at the Nordic Infocenter documentation for nRF52 Series:nRF25833:GPIO.&lt;/p&gt;
&lt;p&gt;I agree that the ambiguity is related to how the two GPIO:DETECT signals are joined to trigger the one GPIOTE:EVENTS_PORT, which is why I think it would be very helpful to have both a logic and timing diagram. In that sense, GPIO:Figure 1 isn&amp;#39;t &amp;quot;wrong&amp;quot;, just incomplete.&lt;/p&gt;
&lt;p&gt;At the start of your reply, there is an implication that there are two DETECT signals; on per port. At the end, you quote the GPIOTE text, which sounds like there is only one DETECT signal.&lt;/p&gt;
&lt;p&gt;The problem is that one ISR has to service interrupts for two ports. This is different from other peripherals (e.g. I2c), where each instance has its own interrupt handler. So if P0-&amp;gt;LATCH has a bit set and P1-&amp;gt;LATCH has a bit set then both have to be cleared in the one ISR. In this scenario, if I clear the bit in P0-&amp;gt;LATCH will a new event be generated, even though I haven&amp;#39;t cleared P1-&amp;gt;LATCH, yet? If so, that means my ISR is going to be re-entered before I service the P1 bits. If not, then there&amp;#39;s a race condition getting both LATCH registers clear. Both seem fraught with peril. But knowing which is correct would be helpful.&lt;/p&gt;
&lt;p&gt;All of this seemed perfectly clear when there is one port, but maddeningly unclear when there are two. Pictures are nice. &lt;span class="emoticon" data-url="https://devzone.nordicsemi.com/cfs-file/__key/system/emoji/1f642.svg" title="Slight smile"&gt;&amp;#x1f642;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: NRF_GPIOTE EVENTS_PORT woes (again)</title><link>https://devzone.nordicsemi.com/thread/390492?ContentTypeID=1</link><pubDate>Wed, 12 Oct 2022 15:05:27 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:9b0145a0-030c-48fb-ae11-7c2f254b61e4</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;Hello again,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I have done some digging here.&lt;/p&gt;
&lt;p&gt;I see your point about the documentation seems wrong, but the GPIO chapter do describe each port individually, so&amp;nbsp;it do seem fine if you look at it this way (I do however have some additional information about how the DETECT signal is&amp;nbsp;&amp;quot;joined&amp;quot; from each port to the GPIOTE module at the end here):&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/3252.pastedimage1665585131354v3.png" alt=" " /&gt;&lt;/p&gt;
&lt;p&gt;But to answer your most pressing problem about GPIO_EVENT, DETECT and SENSE I want to refer to the following chapter:&lt;br /&gt;&lt;a href="https://infocenter.nordicsemi.com/topic/ps_nrf52833/gpio.html#concept_o12_bgv_bs"&gt;https://infocenter.nordicsemi.com/topic/ps_nrf52833/gpio.html#concept_o12_bgv_bs&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;quot;The LDETECT signal will be set high when one or more bits in the LATCH register are 1. The LDETECT signal will be set low when all bits in the LATCH register are successfully cleared to 0.&lt;/p&gt;
&lt;p&gt;If one or more bits in the LATCH register are 1 after the CPU has performed a clear operation on the LATCH register, a rising edge will be generated on the LDETECT signal. This is illustrated in DETECT signal behavior.&amp;quot;&lt;/p&gt;
&lt;p&gt;With DETECTMODE=LDETECT, the DETECT signal comes from LATCH instead of directly from pins, and if you clear LATCH, it automatically pulls the DETECT low in order to generate a new edge. It&amp;#39;s important that you use LDETECT in this case, because I have received confirmation from one of the designers that&amp;nbsp;the DETECT signal is gated by LATCH clearing &lt;strong&gt;*after*&lt;/strong&gt; OR&amp;#39;ing all port+pin contributions (but only when DETECTMODE=LDETECT.) The &amp;quot;masking&amp;quot; of the LATCH clearing occurs for 16 clock cycles.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Based on the above I do believe the implementation&amp;nbsp;now is safe&amp;nbsp;to always trigger the Port event by using LDETECT, ref: &amp;quot;PORT is an event that can be generated from multiple input pins using the GPIO DETECT signal. The event will be generated on the rising edge of the DETECT signal.&amp;quot;&lt;/p&gt;
&lt;p&gt;Best regards,&lt;br /&gt;Kenneth&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: NRF_GPIOTE EVENTS_PORT woes (again)</title><link>https://devzone.nordicsemi.com/thread/390078?ContentTypeID=1</link><pubDate>Mon, 10 Oct 2022 15:05:07 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:aa9925b5-8f2e-4d3c-9c6e-7cb2c03c806f</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;Let me check internally and get back to you (this will take several days).&lt;/p&gt;
&lt;p&gt;Kenneth&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: NRF_GPIOTE EVENTS_PORT woes (again)</title><link>https://devzone.nordicsemi.com/thread/390031?ContentTypeID=1</link><pubDate>Mon, 10 Oct 2022 13:15:35 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:eb47ef57-4028-4d70-ae86-e69e05935678</guid><dc:creator>jsheaney</dc:creator><description>&lt;p&gt;Kenneth, Thanks for chiming in. I&amp;#39;m hoping a new perspective will help me set this aside.&lt;/p&gt;
&lt;p&gt;1) The documentation is wrong, as I indicated. There are two LATCH registers and two DETECTMODE registers. The 52833 documentation should be updated, accordingly, so that we can see how the hardware really works.&lt;/p&gt;
&lt;p&gt;2) The GPIOTE documentation says &amp;quot;The event will be generated on the rising edge of the DETECT signal.&amp;quot;. That means the DETECT signal must be brought low before there can be a (subsequent) rising edge. Simply setting&amp;nbsp;the&amp;nbsp;&lt;span&gt;EVENTS_PORT register to 0 will not cause another interrupt.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;3) The race condition stems from the fact that you have to read two different (LATCH) registers to detect the bits that need to be cleared because there is no way to read the DETECT signal. (It would be nice if there was a secret register somewhere that would allow it.) Since these bits are set in hardware, the setting of them cannot be disabled while reading&amp;nbsp;the registers. That means while reading P0-&amp;gt;LATCH, bits in P1-&amp;gt;LATCH can be set and vice versa. This is really the crux of the problem. Typically, if you run into a situation like this, you&amp;nbsp;create a critical region around your non-atomic reads. In this case, you can&amp;#39;t. There doesn&amp;#39;t appear to be a way to stop the hardware from updating the LATCH registers.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;4)&amp;nbsp;I installed a workaround by looking at the LATCH registers in my main (non-interrupt) loop. Sometimes I see a bit set in a&amp;nbsp;LATCH register. (To be clear, this should never happen because an interrupt should be generated before my main context code has a chance to read it.) Upon detection, I set the LATCH bits back to 0 and that keeps the system going, although I obviously lost an interrupt in the process.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: NRF_GPIOTE EVENTS_PORT woes (again)</title><link>https://devzone.nordicsemi.com/thread/389977?ContentTypeID=1</link><pubDate>Mon, 10 Oct 2022 10:56:04 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:829e6f9a-138e-4479-9bf3-78ade829c1fc</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;I am not sure if I fully understand the problem, if you in the gpiote interrupt handler find that the&amp;nbsp;EVENT_PORT has occured (and clear it) and then check the&amp;nbsp;LATCH register(s) (and clear those set), this may iterate a few times depending whether new EVENT_PORT/LATCH are triggered during gpiote handler execution as you write, however if there are new source(s) for the DETECT signal triggering the EVENT_PORT, after EVENT_PORT was cleared, would then not the gpiote interrupt be fired again immediately after such that those also can be handled?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Looking at the&amp;nbsp;nrfx_gpiote_irq_handler() and port_event_handler() implementation in nrfx_gpiote.c I don&amp;#39;t quite understand where the race condition you are afraid of occurs:&lt;br /&gt;&lt;a href="https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_gpiote.c#L1316"&gt;https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_gpiote.c#L1316&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&lt;a href="https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_gpiote.c#L1157"&gt;https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_gpiote.c#L1157&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you are the nRF5 SDK you may need to look at this file instead:&lt;br /&gt;&lt;a href="https://github.com/NordicSemiconductor/nrfx/blob/nrfx-1.x/master/drivers/src/nrfx_gpiote.c"&gt;https://github.com/NordicSemiconductor/nrfx/blob/nrfx-1.x/master/drivers/src/nrfx_gpiote.c&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Edit: I might be able to see a problem if you have fast toggling input signal (e.g. &amp;gt;1kHz range), but in that case maybe using IN event is a better suggestion than PORT_EVENT for those pins in specific.&lt;/p&gt;
&lt;p&gt;Kenneth&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>