<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Doing I/O from an interrupt handler in S32K</title>
    <link>https://community.nxp.com/t5/S32K/Doing-I-O-from-an-interrupt-handler/m-p/2296444#M56208</link>
    <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;DIV&gt;Blocking I/O from an ISR won’t work with the S32K1 SDK. LPSPI_DRV_MasterTransferBlocking() waits on an OSIF semaphore; in ISR context there’s no place to block and no tick/time base to advance, so it hangs. Use the non‑blocking API (LPSPI_DRV_MasterTransfer) and complete the transfer in the LPSPI ISR/callback, then signal a task/main loop. Also, SysTick fires on timer wrap, but its handler only runs when not masked and with sufficient NVIC priority—so if PRIMASK is set or you’re in a higher‑priority ISR, it will be deferred.&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;
&lt;DIV&gt;The cookbook projects are deliberately lightweight, showing peripheral use directly without the higher‑level driver abstractions; they’re intended as learning starting points, not production usage. If you want NXP driver‑style examples, look to SDK, or rather RTD driver/example projects rather than the cookbook.&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;BR, Petr&lt;/DIV&gt;
&lt;/DIV&gt;</description>
    <pubDate>Tue, 20 Jan 2026 09:10:06 GMT</pubDate>
    <dc:creator>PetrS</dc:creator>
    <dc:date>2026-01-20T09:10:06Z</dc:date>
    <item>
      <title>Doing I/O from an interrupt handler</title>
      <link>https://community.nxp.com/t5/S32K/Doing-I-O-from-an-interrupt-handler/m-p/2296205#M56201</link>
      <description>&lt;P&gt;The relevant parameters for this question are as follows:&lt;/P&gt;&lt;P&gt;1. IDE: S32 DS for ARM v 2.2 (Yes, I know this is old, but so is the product in question; we need to support the existing code)&lt;/P&gt;&lt;P&gt;2. Chip: S32K148&lt;/P&gt;&lt;P&gt;3. OS: Windows 11&lt;/P&gt;&lt;P&gt;4. System OS: Bare metal&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Attempting to do any kind of SPI Master transfer in an ISR hangs, and usually the API that was interrupted is a blocking I/O (I2C or SPI) call.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;On a blocking call (to&amp;nbsp;LPSPI_DRV_MasterTransferBlocking() ), the call hangs because sysTick interrupts do not seem to be happening, so the MCU does not get a sense of elapsing time.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;On a non-blocking call (LPSPI_DRV_MasterTransfer() followed by&amp;nbsp;LPSPI_DRV_MasterGetTransferStatus(SPI1, &amp;amp;byte_remaining) ),&amp;nbsp;byte_remaining stays at the original value. I have attempted to add a call to&amp;nbsp; LPSPI_DRV_MasterAbortTransfer(SPI1) before calling&amp;nbsp;LPSPI_DRV_MasterTransfer() for the async transfer, but the result is the same.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;On a semi-related question, what triggers the&amp;nbsp;SysTick_Handler() ? My intuition says it should be running all the time increasing the tick count every 1ms, but putting a break point in the body of it seems to hit only some time. Strangely, it is sometimes not hit even when a blocking SPI transfer is successful, which should be arming the system timer if it was unarmed before.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Another semi-related question is that in the S32 Cookbook example code for SPI, there are no use of the SDK provided APIs; the examples do all the register bit banging directly. Are there any examples that are closer to production worthy code, in that they at least call the NXP APIs instead of re-inventing the wheel?&lt;/P&gt;</description>
      <pubDate>Tue, 20 Jan 2026 00:33:25 GMT</pubDate>
      <guid>https://community.nxp.com/t5/S32K/Doing-I-O-from-an-interrupt-handler/m-p/2296205#M56201</guid>
      <dc:creator>durga_choudhury</dc:creator>
      <dc:date>2026-01-20T00:33:25Z</dc:date>
    </item>
    <item>
      <title>Re: Doing I/O from an interrupt handler</title>
      <link>https://community.nxp.com/t5/S32K/Doing-I-O-from-an-interrupt-handler/m-p/2296444#M56208</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;DIV&gt;Blocking I/O from an ISR won’t work with the S32K1 SDK. LPSPI_DRV_MasterTransferBlocking() waits on an OSIF semaphore; in ISR context there’s no place to block and no tick/time base to advance, so it hangs. Use the non‑blocking API (LPSPI_DRV_MasterTransfer) and complete the transfer in the LPSPI ISR/callback, then signal a task/main loop. Also, SysTick fires on timer wrap, but its handler only runs when not masked and with sufficient NVIC priority—so if PRIMASK is set or you’re in a higher‑priority ISR, it will be deferred.&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;
&lt;DIV&gt;The cookbook projects are deliberately lightweight, showing peripheral use directly without the higher‑level driver abstractions; they’re intended as learning starting points, not production usage. If you want NXP driver‑style examples, look to SDK, or rather RTD driver/example projects rather than the cookbook.&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;BR, Petr&lt;/DIV&gt;
&lt;/DIV&gt;</description>
      <pubDate>Tue, 20 Jan 2026 09:10:06 GMT</pubDate>
      <guid>https://community.nxp.com/t5/S32K/Doing-I-O-from-an-interrupt-handler/m-p/2296444#M56208</guid>
      <dc:creator>PetrS</dc:creator>
      <dc:date>2026-01-20T09:10:06Z</dc:date>
    </item>
    <item>
      <title>Re: Doing I/O from an interrupt handler</title>
      <link>https://community.nxp.com/t5/S32K/Doing-I-O-from-an-interrupt-handler/m-p/2296719#M56218</link>
      <description>&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://community.nxp.com/t5/user/viewprofilepage/user-id/52961"&gt;@PetrS&lt;/a&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thank you for your response, but I am afraid I don't really understand it.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;What you seem to be saying is that doing blocking I/O inside an ISR is a bad idea, and I agree. But why should it not work? The tick counter increments in an interrupt handler that priority -1, that is higher than any I/O interrupt priority. And I am not changing any interrupt mask in my code; does the driver change it under the hood?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Our application is bare metal (single threaded), so waiting in an ISR context and application context is pretty much the same thing. The only difference is that in an ISR context, other I/O interrupts will be blocked. But this is exactly what I want anyway. The timer ISR, however, should not be blocked because of the higher priority. I have tried adding a call to ENABLE_INTERRPUTS() on the first line of the ISR, but it made no difference.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have tried the non-blocking version also, and that also hangs, in a different way.&amp;nbsp;&lt;SPAN&gt;On a non-blocking call (LPSPI_DRV_MasterTransfer() followed by&amp;nbsp;LPSPI_DRV_MasterGetTransferStatus(SPI1, &amp;amp;byte_remaining) ),&amp;nbsp;byte_remaining stays at the original value. I have attempted to add a call to&amp;nbsp; LPSPI_DRV_MasterAbortTransfer(SPI1) before calling&amp;nbsp;LPSPI_DRV_MasterTransfer() for the async transfer, but the result is the same. Both of the above API calls are made from the ISR. The use case is that if the user presses a button, a GPIO interrupt is fired and it wants to read a value over SPI.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN&gt;One thing worth pointing out again is that the API that the ISR is interrupting is a blocking SPI transfer. Adding a call to&amp;nbsp;LPSPI_DRV_MasterAbortTransfer() in the ISR before starting the new transfer also did not help.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN&gt;I am on a very tight deadline on this issue; any help is greatly appreciated.&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Tue, 20 Jan 2026 14:21:42 GMT</pubDate>
      <guid>https://community.nxp.com/t5/S32K/Doing-I-O-from-an-interrupt-handler/m-p/2296719#M56218</guid>
      <dc:creator>durga_choudhury</dc:creator>
      <dc:date>2026-01-20T14:21:42Z</dc:date>
    </item>
    <item>
      <title>Re: Doing I/O from an interrupt handler</title>
      <link>https://community.nxp.com/t5/S32K/Doing-I-O-from-an-interrupt-handler/m-p/2296759#M56221</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;DIV&gt;
&lt;P&gt;OK, then simply interrupts priorities could cause this behavior. The blocking API hangs simply because the LPSPI ISR cannot run while the GPIO ISR is active if both interrupts have the same priority. The blocking call waits for the ISR to finish the transfer and post the semaphore - but that ISR never gets CPU time until the GPIO ISR exits. The SDK’s driver indeed finishes transfers in the LPSPI interrupt, and only then posts the semaphore to release the blocking call, so equal‑priority ISRs will deadlock the transfer this way.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The non‑blocking API behaves the same: if called from a GPIO ISR of equal priority, the LPSPI ISR cannot preempt it, so byte_remaining never changes because the driver state machine is never serviced by the LPSPI IRQ. Only after raising LPSPI to a higher priority (numerically lower value) will the LPSPI interrupt fire immediately, complete the transfer, and allow both blocking and non‑blocking APIs to work as expected. Try&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;!--ScriptorStartFragment--&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;DIV class="scriptor-paragraph"&gt;&lt;SPAN&gt;/* Smaller number = higher priority on Cortex-M */&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;DIV class="scriptor-paragraph"&gt;&lt;SPAN&gt;INT_SYS_SetPriority&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;SysTick_IRQn&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;/SPAN&gt; &lt;SPAN&gt;0&lt;/SPAN&gt;&lt;SPAN&gt;)&lt;/SPAN&gt;&lt;SPAN&gt;;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;// if you rely on tick timeouts&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;DIV class="scriptor-paragraph"&gt;&lt;SPAN&gt;INT_SYS_SetPriority&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;LPSPI1_IRQn&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;/SPAN&gt; &lt;SPAN&gt;1&lt;/SPAN&gt;&lt;SPAN&gt;)&lt;/SPAN&gt;&lt;SPAN&gt;;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;// must be higher than GPIO&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;DIV class="scriptor-paragraph"&gt;&lt;SPAN&gt;INT_SYS_SetPriority&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;PORTC_IRQn&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;/SPAN&gt; &lt;SPAN&gt;2&lt;/SPAN&gt;&lt;SPAN&gt;)&lt;/SPAN&gt;&lt;SPAN&gt;;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;// your button’s PORTx IRQ&lt;!--ScriptorEndFragment--&gt;&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;DIV class="scriptor-paragraph"&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV class="scriptor-paragraph"&gt;
&lt;DIV&gt;Note: regardless of the priority fix, it’s still advisable not to use the blocking SPI API inside an ISR, and likewise not to wait inside an ISR for a non‑blocking transfer to finish. The S32K LPSPI driver progresses transfers in its interrupt handler, and long ISRs can prevent other interrupts from running.&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;BR, Petr&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;P&gt;&lt;LI-WRAPPER&gt;&lt;/LI-WRAPPER&gt;&lt;/P&gt;
&lt;/DIV&gt;</description>
      <pubDate>Tue, 20 Jan 2026 15:32:05 GMT</pubDate>
      <guid>https://community.nxp.com/t5/S32K/Doing-I-O-from-an-interrupt-handler/m-p/2296759#M56221</guid>
      <dc:creator>PetrS</dc:creator>
      <dc:date>2026-01-20T15:32:05Z</dc:date>
    </item>
    <item>
      <title>Re: Doing I/O from an interrupt handler</title>
      <link>https://community.nxp.com/t5/S32K/Doing-I-O-from-an-interrupt-handler/m-p/2296859#M56227</link>
      <description>&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://community.nxp.com/t5/user/viewprofilepage/user-id/52961"&gt;@PetrS&lt;/a&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thank you very much. The interrupt priority indeed solved the problem. However, I do have a question:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I agree that blocking inside an ISR is not a good idea, but what is the alternative in a single threaded application? I could spin in the application context until the SPI transfer is done. That will allow other I/O interrupts to happen (my understanding is that negative priority interrupts will fire anyway; they are not disabled when a positive priority ISR is entered). But in my situation doing overlapping I/O is neither possible nor desirable.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;1. It is not possible because the S32K148 is the bus master for all the buses. So if it is doing a SPI transfer in an ISR, it cannot possibly drive another I/O bus and therefore cannot trigger interrupts.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;2. It is not desirable because there could be shared globals between the ISRs, so I don't want to start a new I/O until the current one is complete.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;For a single threaded bare metal application, what would be your recommendation to handle this situation?&lt;/P&gt;</description>
      <pubDate>Tue, 20 Jan 2026 20:27:00 GMT</pubDate>
      <guid>https://community.nxp.com/t5/S32K/Doing-I-O-from-an-interrupt-handler/m-p/2296859#M56227</guid>
      <dc:creator>durga_choudhury</dc:creator>
      <dc:date>2026-01-20T20:27:00Z</dc:date>
    </item>
    <item>
      <title>Re: Doing I/O from an interrupt handler</title>
      <link>https://community.nxp.com/t5/S32K/Doing-I-O-from-an-interrupt-handler/m-p/2297270#M56245</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;DIV&gt;even though it now “works” you should still&amp;nbsp;discourage doing the SPI transfer inside the ISR.&amp;nbsp;
&lt;DIV&gt;If you ever change priorities later, or add another peripheral, you can easily re‑create the deadlock condition you just diagnosed.&amp;nbsp;The safest design would be always to keep ISRs short and defer real work to the main loop.&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;DIV&gt;
&lt;P&gt;Use the ISR only as a trigger; perform the SPI transfer synchronously in main() or as a non‑blocking transfer initiated in the ISR but completed by the LPSPI ISR, and main waits for the completion flag.&lt;/P&gt;
&lt;P&gt;BR, Petr&lt;/P&gt;
&lt;/DIV&gt;</description>
      <pubDate>Wed, 21 Jan 2026 10:11:19 GMT</pubDate>
      <guid>https://community.nxp.com/t5/S32K/Doing-I-O-from-an-interrupt-handler/m-p/2297270#M56245</guid>
      <dc:creator>PetrS</dc:creator>
      <dc:date>2026-01-21T10:11:19Z</dc:date>
    </item>
  </channel>
</rss>

