title: ESP8266/Arduino: Why is it necessary to add the ICACHE_RAM_ATTR macro to ISRs and functions called from there?
body: <p><em>Note: Since <a href="https://github.com/esp8266/Arduino/releases/tag/3.0.0" rel="nofollow noreferrer">esp8266/Arduino release 3.0.0</a> ICACHE_RAM_ATTR has been changed to IRAM_ATTR. For future readers, I updated the links to the <a href="https://arduino-esp8266.readthedocs.io/" rel="nofollow noreferrer">ESP8266 Arduino Core docs</a>, but left the rest of the question unchanged.</em></p>
  <hr />
  <p>I read that I <a href="https://arduino-esp8266.readthedocs.io/en/latest/reference.html?highlight=IRAM_ATTR#interrupts" rel="nofollow noreferrer">need to add the ICACHE_RAM_ATTR macro to interrup service routines (ISRs)</a> <a href="https://arduino-esp8266.readthedocs.io/en/latest/faq/a02-my-esp-crashes.html?highlight=IRAM_ATTR#other-causes-for-crashes" rel="nofollow noreferrer">and to every function that is called from there</a> in my Arduino code for ESP8266 to prevent random crashes. I also found <a href="https://bbs.espressif.com/viewtopic.php?t=1183" rel="nofollow noreferrer">an explanation of what the macro ICACHE_RAM_ATTR does</a>, although I'm not sure if the explanation, which is for the Espressif ESP8266 SDK, is also true for Arduino on ESP8266. And I did not understand why I need to add the macro to ISRs.</p>
  <p><strong>First question:</strong> Why do I need to add the ICACHE_RAM_ATTR macro to ISRs and all functions called from there?</p>
  <p>Next question is, what happens if I force inlining a function that is called from an ISR:</p>
  <pre><code>inline void doStuff() __attribute__((__always_inline__)) { // &lt;-- necessary to add ICACHE_RAM_ATTR here?
      // no more function calls here
  }
  
  void ICACHE_RAM_ATTR handleInterrupt() {
      doStuff();
  }
  </code></pre>
  <p><strong>Second question:</strong> Do I need to add the ICACHE_RAM_ATTR macro to functions that are forced to be inlined?</p>