From 4f0b0a709da82d5ac8dfe90343f8389e10169a85 Mon Sep 17 00:00:00 2001
From: StanJ <53401742+Tech-TX@users.noreply.github.com>
Date: Tue, 10 Dec 2019 20:21:09 -0600
Subject: [PATCH 1/5] change to make inline helpers truly inline [issue 6875]

---
 cores/esp8266/core_esp8266_si2c.cpp | 122 ++++++++++++++--------------
 1 file changed, 62 insertions(+), 60 deletions(-)

diff --git a/cores/esp8266/core_esp8266_si2c.cpp b/cores/esp8266/core_esp8266_si2c.cpp
index 58442e4147..d21b65af48 100644
--- a/cores/esp8266/core_esp8266_si2c.cpp
+++ b/cores/esp8266/core_esp8266_si2c.cpp
@@ -96,36 +96,37 @@ class Twi
     void ICACHE_RAM_ATTR onTwipEvent(uint8_t status);
 
     // Inline helpers
-    inline void SDA_LOW()
+    static inline void SDA_LOW(const int twi_sda) __attribute__((always_inline))
     {
         GPES = (1 << twi_sda);
     }
-    inline void SDA_HIGH()
+    static  inline void SDA_HIGH(const int twi_sda) __attribute__((always_inline))
     {
         GPEC = (1 << twi_sda);
     }
-    inline bool SDA_READ()
-    {
+	static inline bool SDA_READ(const int twi_sda) __attribute__((always_inline))
+	{
         return (GPI & (1 << twi_sda)) != 0;
     }
-    inline void SCL_LOW()
+    static inline void SCL_LOW(const int twi_scl) __attribute__((always_inline))
     {
         GPES = (1 << twi_scl);
     }
-    inline void SCL_HIGH()
+    static inline void SCL_HIGH(const int twi_scl) __attribute__((always_inline))
     {
         GPEC = (1 << twi_scl);
     }
-    inline bool SCL_READ()
-    {
+	static inline bool SCL_READ(const int twi_scl) __attribute__((always_inline))
+	{
         return (GPI & (1 << twi_scl)) != 0;
     }
+
     // Handle the case where a slave needs to stretch the clock with a time-limited busy wait
     inline void WAIT_CLOCK_STRETCH()
     {
         esp8266::polledTimeout::oneShotFastUs timeout(twi_clockStretchLimit);
         esp8266::polledTimeout::periodicFastUs yieldTimeout(5000);
-        while(!timeout && !SCL_READ())  // outer loop is stretch duration up to stretch limit
+        while(!timeout && !SCL_READ(twi_scl))  // outer loop is stretch duration up to stretch limit
         { 
             if (yieldTimeout)   // inner loop yields every 5ms
                 yield();
@@ -277,44 +278,44 @@ void ICACHE_RAM_ATTR Twi::busywait(unsigned char v)
 
 bool Twi::write_start(void)
 {
-    SCL_HIGH();
-    SDA_HIGH();
-    if (!SDA_READ())
+    SCL_HIGH(twi_scl);
+    SDA_HIGH(twi_sda);
+    if (!SDA_READ(twi_sda))
     {
         return false;
     }
     busywait(twi_dcount);
-    SDA_LOW();
+    SDA_LOW(twi_sda);
     busywait(twi_dcount);
     return true;
 }
 
 bool Twi::write_stop(void)
 {
-    SCL_LOW();
-    SDA_LOW();
+    SCL_LOW(twi_scl);
+    SDA_LOW(twi_sda);
     busywait(twi_dcount);
-    SCL_HIGH();
+    SCL_HIGH(twi_scl);
     WAIT_CLOCK_STRETCH();
     busywait(twi_dcount);
-    SDA_HIGH();
+    SDA_HIGH(twi_sda);
     busywait(twi_dcount);
     return true;
 }
 
 bool Twi::write_bit(bool bit)
 {
-    SCL_LOW();
+    SCL_LOW(twi_scl);
     if (bit)
     {
-        SDA_HIGH();
+        SDA_HIGH(twi_sda);
     }
     else
     {
-        SDA_LOW();
+        SDA_LOW(twi_sda);
     }
     busywait(twi_dcount + 1);
-    SCL_HIGH();
+    SCL_HIGH(twi_scl);
     WAIT_CLOCK_STRETCH();
     busywait(twi_dcount);
     return true;
@@ -322,12 +323,12 @@ bool Twi::write_bit(bool bit)
 
 bool Twi::read_bit(void)
 {
-    SCL_LOW();
-    SDA_HIGH();
+    SCL_LOW(twi_scl);
+    SDA_HIGH(twi_sda);
     busywait(twi_dcount + 2);
-    SCL_HIGH();
+    SCL_HIGH(twi_scl);
     WAIT_CLOCK_STRETCH();
-    bool bit = SDA_READ();
+    bool bit = SDA_READ(twi_sda);
     busywait(twi_dcount);
     return bit;
 }
@@ -392,7 +393,7 @@ unsigned char Twi::writeTo(unsigned char address, unsigned char * buf, unsigned
         // busywait(twi_dcount);
     }
     i = 0;
-    while (!SDA_READ() && (i++) < 10)
+    while (!SDA_READ(twi_sda) && (i++) < 10)
     {
         twi_scl_valley();
         busywait(twi_dcount);
@@ -431,7 +432,7 @@ unsigned char Twi::readFrom(unsigned char address, unsigned char* buf, unsigned
         // busywait(twi_dcount);
     }
     i = 0;
-    while (!SDA_READ() && (i++) < 10)
+    while (!SDA_READ(twi_sda) && (i++) < 10)
     {
         twi_scl_valley();
         busywait(twi_dcount);
@@ -442,21 +443,21 @@ unsigned char Twi::readFrom(unsigned char address, unsigned char* buf, unsigned
 uint8_t Twi::status()
 {
     WAIT_CLOCK_STRETCH();  // wait for a slow slave to finish
-    if (!SCL_READ())
+    if (!SCL_READ(twi_scl))
     {
         return I2C_SCL_HELD_LOW;  // SCL held low by another device, no procedure available to recover
     }
 
     int clockCount = 20;
-    while (!SDA_READ() && clockCount-- > 0)   // if SDA low, read the bits slaves have to sent to a max
+    while (!SDA_READ(twi_sda) && clockCount-- > 0)   // if SDA low, read the bits slaves have to sent to a max
     {
         read_bit();
-        if (!SCL_READ())
+        if (!SCL_READ(twi_scl))
         {
             return I2C_SCL_HELD_LOW_AFTER_READ; // I2C bus error. SCL held low beyond slave clock stretch time
         }
     }
-    if (!SDA_READ())
+    if (!SDA_READ(twi_sda))
     {
         return I2C_SDA_HELD_LOW;  // I2C bus error. SDA line held low by slave/another_master after n bits.
     }
@@ -506,13 +507,13 @@ inline void ICACHE_RAM_ATTR Twi::reply(uint8_t ack)
     if (ack)
     {
         //TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
-        SCL_HIGH();		// _BV(TWINT)
+        SCL_HIGH(twi.twi_scl);		// _BV(TWINT)
         twi_ack = 1; 	// _BV(TWEA)
     }
     else
     {
         //TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
-        SCL_HIGH();		// _BV(TWINT)
+        SCL_HIGH(twi.twi_scl);		// _BV(TWINT)
         twi_ack = 0;	// ~_BV(TWEA)
     }
 }
@@ -521,10 +522,10 @@ inline void ICACHE_RAM_ATTR Twi::stop(void)
 {
     // send stop condition
     //TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
-    SCL_HIGH();		// _BV(TWINT)
+    SCL_HIGH(twi.twi_scl);		// _BV(TWINT)
     twi_ack = 1;	// _BV(TWEA)
     busywait(5);	// Maybe this should be here
-    SDA_HIGH();		// _BV(TWSTO)
+    SDA_HIGH(twi.twi_sda);		// _BV(TWSTO)
     // update twi state
     twi_state = TWI_READY;
 }
@@ -533,9 +534,9 @@ inline void ICACHE_RAM_ATTR Twi::releaseBus(void)
 {
     // release bus
     //TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
-    SCL_HIGH();		// _BV(TWINT)
+    SCL_HIGH(twi.twi_scl);		// _BV(TWINT)
     twi_ack = 1; 	// _BV(TWEA)
-    SDA_HIGH();
+    SDA_HIGH(twi.twi_sda);
 
     // update twi state
     twi_state = TWI_READY;
@@ -616,11 +617,11 @@ void ICACHE_RAM_ATTR Twi::onTwipEvent(uint8_t status)
         bitCount--;
         if (twi_data & 0x80)
         {
-            SDA_HIGH();
+            SDA_HIGH(twi.twi_sda);
         }
         else
         {
-            SDA_LOW();
+            SDA_LOW(twi.twi_sda);
         }
         twi_data <<= 1;
 
@@ -652,9 +653,9 @@ void ICACHE_RAM_ATTR Twi::onTwipEvent(uint8_t status)
 
 void Twi::twi_scl_valley(void)
 {
-    SCL_LOW();
+    SCL_LOW(twi_scl);
     busywait(twi_dcount);
-    SCL_HIGH();
+    SCL_HIGH(twi_scl);
     WAIT_CLOCK_STRETCH();
 }
 
@@ -714,8 +715,9 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
     unsigned int scl;
 
     // Store bool return in int to reduce final code size.
-    sda = twi.SDA_READ();
-    scl = twi.SCL_READ();
+	
+    sda = twi.SDA_READ(twi.twi_sda);
+    scl = twi.SCL_READ(twi.twi_scl);
 
     twi.twip_status = 0xF8;		// reset TWI status
 
@@ -758,7 +760,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
                 }
                 else
                 {
-                    twi.SDA_LOW();
+                    twi.SDA_LOW(twi.twi_sda);
                 }
             }
             else
@@ -769,7 +771,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
                 }
                 else
                 {
-                    twi.SDA_LOW();
+                    twi.SDA_LOW(twi.twi_sda);
                 }
             }
             twi.twip_state = TWIP_WAIT_ACK;
@@ -787,13 +789,13 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
             {
                 if ((twi.twi_data & 0xFE) != twi.twi_addr)
                 {
-                    twi.SDA_HIGH();
+                    twi.SDA_HIGH(twi.twi_sda);
                     twi.twip_state = TWIP_WAIT_STOP;
                 }
                 else
                 {
-                    twi.SCL_LOW();	// clock stretching
-                    twi.SDA_HIGH();
+                    twi.SCL_LOW(twi.twi_scl);	// clock stretching
+                    twi.SDA_HIGH(twi.twi_sda);
                     twi.twip_mode = TWIPM_ADDRESSED;
                     if (!(twi.twi_data & 0x01))
                     {
@@ -810,8 +812,8 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
             }
             else
             {
-                twi.SCL_LOW();	// clock stretching
-                twi.SDA_HIGH();
+                twi.SCL_LOW(twi.twi_scl);	// clock stretching
+                twi.SDA_HIGH(twi.twi_sda);
                 if (!twi.twi_ack)
                 {
                     twi.onTwipEvent(TW_SR_DATA_NACK);
@@ -838,11 +840,11 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
             twi.bitCount--;
             if (twi.twi_data & 0x80)
             {
-                twi.SDA_HIGH();
+                twi.SDA_HIGH(twi.twi_sda);
             }
             else
             {
-                twi.SDA_LOW();
+                twi.SDA_LOW(twi.twi_sda);
             }
             twi.twi_data <<= 1;
 
@@ -864,7 +866,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
         }
         else
         {
-            twi.SDA_HIGH();
+            twi.SDA_HIGH(twi.twi_sda);
             twi.twip_state = TWIP_READ_ACK;
         }
     }
@@ -888,7 +890,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
         }
         else
         {
-            twi.SCL_LOW();	// clock stretching
+            twi.SCL_LOW(twi.twi_scl);	// clock stretching
             if (twi.twi_ack && twi.twi_ack_rec)
             {
                 twi.onTwipEvent(TW_ST_DATA_ACK);
@@ -911,8 +913,8 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
     unsigned int scl;
 
     // Store bool return in int to reduce final code size.
-    sda = twi.SDA_READ();
-    scl = twi.SCL_READ();
+    sda = twi.SDA_READ(twi.twi_sda);
+    scl = twi.SCL_READ(twi.twi_scl);
 
     int twip_state_mask = S2M(twi.twip_state);
     if (scl)   /* !DATA */
@@ -934,7 +936,7 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
         else IFSTATE(S2M(TWIP_START) | S2M(TWIP_REP_START) | S2M(TWIP_SEND_ACK) | S2M(TWIP_WAIT_ACK) | S2M(TWIP_SLA_R) | S2M(TWIP_REC_ACK) | S2M(TWIP_READ_ACK) | S2M(TWIP_RWAIT_ACK) | S2M(TWIP_WRITE))
         {
             // START or STOP
-            twi.SDA_HIGH();	 // Should not be necessary
+            twi.SDA_HIGH(twi.twi_sda);	 // Should not be necessary
             twi.onTwipEvent(TW_BUS_ERROR);
             twi.twip_mode = TWIPM_WAIT;
             twi.twip_state = TWIP_BUS_ERR;
@@ -944,11 +946,11 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
             if (sda)
             {
                 // STOP
-                twi.SCL_LOW();	// clock stretching
+                twi.SCL_LOW(twi.twi_scl);	// clock stretching
                 ets_timer_disarm(&twi.timer);
                 twi.twip_state = TWIP_IDLE;
                 twi.twip_mode = TWIPM_IDLE;
-                twi.SCL_HIGH();
+                twi.SCL_HIGH(twi.twi_scl);
             }
             else
             {
@@ -978,7 +980,7 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
             else
             {
                 // during first bit in byte transfer - ok
-                twi.SCL_LOW();	// clock stretching
+                twi.SCL_LOW(twi.twi_scl);	// clock stretching
                 twi.onTwipEvent(TW_SR_STOP);
                 if (sda)
                 {

From 0a9e394792d4c6569c9341faf21b0d4c50efa3ff Mon Sep 17 00:00:00 2001
From: StanJ <53401742+Tech-TX@users.noreply.github.com>
Date: Tue, 10 Dec 2019 21:17:29 -0600
Subject: [PATCH 2/5] pulled the inline helpers out of the TWI class [issue
 6875]

---
 cores/esp8266/core_esp8266_si2c.cpp | 90 ++++++++++++++---------------
 1 file changed, 45 insertions(+), 45 deletions(-)

diff --git a/cores/esp8266/core_esp8266_si2c.cpp b/cores/esp8266/core_esp8266_si2c.cpp
index d21b65af48..54924fe504 100644
--- a/cores/esp8266/core_esp8266_si2c.cpp
+++ b/cores/esp8266/core_esp8266_si2c.cpp
@@ -31,6 +31,32 @@ extern "C" {
 #include "ets_sys.h"
 };
 
+    // Inline helpers
+    static inline __attribute__((always_inline)) void SDA_LOW(const int twi_sda)
+    {
+        GPES = (1 << twi_sda);
+    }
+    static inline __attribute__((always_inline)) void SDA_HIGH(const int twi_sda)
+    {
+        GPEC = (1 << twi_sda);
+    }
+	static inline __attribute__((always_inline)) bool SDA_READ(const int twi_sda)
+	{
+        return (GPI & (1 << twi_sda)) != 0;
+    }
+    static inline __attribute__((always_inline)) void SCL_LOW(const int twi_scl)
+    {
+        GPES = (1 << twi_scl);
+    }
+    static inline __attribute__((always_inline)) void SCL_HIGH(const int twi_scl)
+    {
+        GPEC = (1 << twi_scl);
+    }
+	static inline __attribute__((always_inline)) bool SCL_READ(const int twi_scl)
+	{
+        return (GPI & (1 << twi_scl)) != 0;
+    }
+
 
 // Implement as a class to reduce code size by allowing access to many global variables with a single base pointer
 class Twi
@@ -95,32 +121,6 @@ class Twi
     unsigned char read_byte(bool nack);
     void ICACHE_RAM_ATTR onTwipEvent(uint8_t status);
 
-    // Inline helpers
-    static inline void SDA_LOW(const int twi_sda) __attribute__((always_inline))
-    {
-        GPES = (1 << twi_sda);
-    }
-    static  inline void SDA_HIGH(const int twi_sda) __attribute__((always_inline))
-    {
-        GPEC = (1 << twi_sda);
-    }
-	static inline bool SDA_READ(const int twi_sda) __attribute__((always_inline))
-	{
-        return (GPI & (1 << twi_sda)) != 0;
-    }
-    static inline void SCL_LOW(const int twi_scl) __attribute__((always_inline))
-    {
-        GPES = (1 << twi_scl);
-    }
-    static inline void SCL_HIGH(const int twi_scl) __attribute__((always_inline))
-    {
-        GPEC = (1 << twi_scl);
-    }
-	static inline bool SCL_READ(const int twi_scl) __attribute__((always_inline))
-	{
-        return (GPI & (1 << twi_scl)) != 0;
-    }
-
     // Handle the case where a slave needs to stretch the clock with a time-limited busy wait
     inline void WAIT_CLOCK_STRETCH()
     {
@@ -716,8 +716,8 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
 
     // Store bool return in int to reduce final code size.
 	
-    sda = twi.SDA_READ(twi.twi_sda);
-    scl = twi.SCL_READ(twi.twi_scl);
+    sda = SDA_READ(twi.twi_sda);
+    scl = SCL_READ(twi.twi_scl);
 
     twi.twip_status = 0xF8;		// reset TWI status
 
@@ -760,7 +760,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
                 }
                 else
                 {
-                    twi.SDA_LOW(twi.twi_sda);
+                    SDA_LOW(twi.twi_sda);
                 }
             }
             else
@@ -771,7 +771,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
                 }
                 else
                 {
-                    twi.SDA_LOW(twi.twi_sda);
+                    SDA_LOW(twi.twi_sda);
                 }
             }
             twi.twip_state = TWIP_WAIT_ACK;
@@ -789,13 +789,13 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
             {
                 if ((twi.twi_data & 0xFE) != twi.twi_addr)
                 {
-                    twi.SDA_HIGH(twi.twi_sda);
+                    SDA_HIGH(twi.twi_sda);
                     twi.twip_state = TWIP_WAIT_STOP;
                 }
                 else
                 {
-                    twi.SCL_LOW(twi.twi_scl);	// clock stretching
-                    twi.SDA_HIGH(twi.twi_sda);
+                    SCL_LOW(twi.twi_scl);	// clock stretching
+                    SDA_HIGH(twi.twi_sda);
                     twi.twip_mode = TWIPM_ADDRESSED;
                     if (!(twi.twi_data & 0x01))
                     {
@@ -812,8 +812,8 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
             }
             else
             {
-                twi.SCL_LOW(twi.twi_scl);	// clock stretching
-                twi.SDA_HIGH(twi.twi_sda);
+                SCL_LOW(twi.twi_scl);	// clock stretching
+                SDA_HIGH(twi.twi_sda);
                 if (!twi.twi_ack)
                 {
                     twi.onTwipEvent(TW_SR_DATA_NACK);
@@ -840,11 +840,11 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
             twi.bitCount--;
             if (twi.twi_data & 0x80)
             {
-                twi.SDA_HIGH(twi.twi_sda);
+                SDA_HIGH(twi.twi_sda);
             }
             else
             {
-                twi.SDA_LOW(twi.twi_sda);
+                SDA_LOW(twi.twi_sda);
             }
             twi.twi_data <<= 1;
 
@@ -866,7 +866,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
         }
         else
         {
-            twi.SDA_HIGH(twi.twi_sda);
+            SDA_HIGH(twi.twi_sda);
             twi.twip_state = TWIP_READ_ACK;
         }
     }
@@ -890,7 +890,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
         }
         else
         {
-            twi.SCL_LOW(twi.twi_scl);	// clock stretching
+            SCL_LOW(twi.twi_scl);	// clock stretching
             if (twi.twi_ack && twi.twi_ack_rec)
             {
                 twi.onTwipEvent(TW_ST_DATA_ACK);
@@ -913,8 +913,8 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
     unsigned int scl;
 
     // Store bool return in int to reduce final code size.
-    sda = twi.SDA_READ(twi.twi_sda);
-    scl = twi.SCL_READ(twi.twi_scl);
+    sda = SDA_READ(twi.twi_sda);
+    scl = SCL_READ(twi.twi_scl);
 
     int twip_state_mask = S2M(twi.twip_state);
     if (scl)   /* !DATA */
@@ -936,7 +936,7 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
         else IFSTATE(S2M(TWIP_START) | S2M(TWIP_REP_START) | S2M(TWIP_SEND_ACK) | S2M(TWIP_WAIT_ACK) | S2M(TWIP_SLA_R) | S2M(TWIP_REC_ACK) | S2M(TWIP_READ_ACK) | S2M(TWIP_RWAIT_ACK) | S2M(TWIP_WRITE))
         {
             // START or STOP
-            twi.SDA_HIGH(twi.twi_sda);	 // Should not be necessary
+            SDA_HIGH(twi.twi_sda);	 // Should not be necessary
             twi.onTwipEvent(TW_BUS_ERROR);
             twi.twip_mode = TWIPM_WAIT;
             twi.twip_state = TWIP_BUS_ERR;
@@ -946,11 +946,11 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
             if (sda)
             {
                 // STOP
-                twi.SCL_LOW(twi.twi_scl);	// clock stretching
+                SCL_LOW(twi.twi_scl);	// clock stretching
                 ets_timer_disarm(&twi.timer);
                 twi.twip_state = TWIP_IDLE;
                 twi.twip_mode = TWIPM_IDLE;
-                twi.SCL_HIGH(twi.twi_scl);
+                SCL_HIGH(twi.twi_scl);
             }
             else
             {
@@ -980,7 +980,7 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
             else
             {
                 // during first bit in byte transfer - ok
-                twi.SCL_LOW(twi.twi_scl);	// clock stretching
+                SCL_LOW(twi.twi_scl);	// clock stretching
                 twi.onTwipEvent(TW_SR_STOP);
                 if (sda)
                 {

From e34f4d6fed7f58c34ca356fa96f9906bfd23e457 Mon Sep 17 00:00:00 2001
From: StanJ <53401742+Tech-TX@users.noreply.github.com>
Date: Tue, 10 Dec 2019 23:11:50 -0600
Subject: [PATCH 3/5] removed some inlines causing issues [issue 6875]

---
 cores/esp8266/core_esp8266_si2c.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/cores/esp8266/core_esp8266_si2c.cpp b/cores/esp8266/core_esp8266_si2c.cpp
index 54924fe504..320a090615 100644
--- a/cores/esp8266/core_esp8266_si2c.cpp
+++ b/cores/esp8266/core_esp8266_si2c.cpp
@@ -147,7 +147,7 @@ class Twi
     uint8_t transmit(const uint8_t* data, uint8_t length);
     void attachSlaveRxEvent(void (*function)(uint8_t*, size_t));
     void attachSlaveTxEvent(void (*function)(void));
-    inline void ICACHE_RAM_ATTR reply(uint8_t ack);
+    void ICACHE_RAM_ATTR reply(uint8_t ack);
     inline void ICACHE_RAM_ATTR stop(void);
     inline void ICACHE_RAM_ATTR releaseBus(void);
     void enableSlave();
@@ -501,7 +501,7 @@ void Twi::attachSlaveTxEvent(void (*function)(void))
     twi_onSlaveTransmit = function;
 }
 
-inline void ICACHE_RAM_ATTR Twi::reply(uint8_t ack)
+void ICACHE_RAM_ATTR Twi::reply(uint8_t ack)
 {
     // transmit master read ready signal, with or without ack
     if (ack)

From cf1d9fd43f5af306873d9151d46de68001a00c89 Mon Sep 17 00:00:00 2001
From: StanJ <53401742+Tech-TX@users.noreply.github.com>
Date: Wed, 11 Dec 2019 06:16:10 -0600
Subject: [PATCH 4/5] removed 2 more inlines from slave timeout section [issue
 6875]

---
 cores/esp8266/core_esp8266_si2c.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/cores/esp8266/core_esp8266_si2c.cpp b/cores/esp8266/core_esp8266_si2c.cpp
index 320a090615..6e5266d672 100644
--- a/cores/esp8266/core_esp8266_si2c.cpp
+++ b/cores/esp8266/core_esp8266_si2c.cpp
@@ -148,8 +148,8 @@ class Twi
     void attachSlaveRxEvent(void (*function)(uint8_t*, size_t));
     void attachSlaveTxEvent(void (*function)(void));
     void ICACHE_RAM_ATTR reply(uint8_t ack);
-    inline void ICACHE_RAM_ATTR stop(void);
-    inline void ICACHE_RAM_ATTR releaseBus(void);
+    void ICACHE_RAM_ATTR stop(void);
+    void ICACHE_RAM_ATTR releaseBus(void);
     void enableSlave();
 };
 

From 1d203544053ef80bd4c36881e14ee84695204761 Mon Sep 17 00:00:00 2001
From: StanJ <53401742+Tech-TX@users.noreply.github.com>
Date: Wed, 11 Dec 2019 21:16:40 -0600
Subject: [PATCH 5/5] removed 2 more inline attributes on public functions,
 moved twi_scl_valley up into the master section [issue 6875]

---
 cores/esp8266/core_esp8266_si2c.cpp | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/cores/esp8266/core_esp8266_si2c.cpp b/cores/esp8266/core_esp8266_si2c.cpp
index 6e5266d672..858cdda09a 100644
--- a/cores/esp8266/core_esp8266_si2c.cpp
+++ b/cores/esp8266/core_esp8266_si2c.cpp
@@ -440,6 +440,14 @@ unsigned char Twi::readFrom(unsigned char address, unsigned char* buf, unsigned
     return 0;
 }
 
+void Twi::twi_scl_valley(void)
+{
+    SCL_LOW(twi_scl);
+    busywait(twi_dcount);
+    SCL_HIGH(twi_scl);
+    WAIT_CLOCK_STRETCH();
+}
+
 uint8_t Twi::status()
 {
     WAIT_CLOCK_STRETCH();  // wait for a slow slave to finish
@@ -501,6 +509,9 @@ void Twi::attachSlaveTxEvent(void (*function)(void))
     twi_onSlaveTransmit = function;
 }
 
+// DO NOT INLINE, inlining reply() in combination with compiler optimizations causes function breakup into 
+// parts and the ICACHE_RAM_ATTR isn't propagated correctly to all parts, which of course causes crashes.
+// TODO: test with gcc 9.x and if it still fails, disable optimization with -fdisable-ipa-fnsplit
 void ICACHE_RAM_ATTR Twi::reply(uint8_t ack)
 {
     // transmit master read ready signal, with or without ack
@@ -518,7 +529,7 @@ void ICACHE_RAM_ATTR Twi::reply(uint8_t ack)
     }
 }
 
-inline void ICACHE_RAM_ATTR Twi::stop(void)
+void ICACHE_RAM_ATTR Twi::stop(void)
 {
     // send stop condition
     //TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
@@ -530,7 +541,7 @@ inline void ICACHE_RAM_ATTR Twi::stop(void)
     twi_state = TWI_READY;
 }
 
-inline void ICACHE_RAM_ATTR Twi::releaseBus(void)
+void ICACHE_RAM_ATTR Twi::releaseBus(void)
 {
     // release bus
     //TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
@@ -651,14 +662,6 @@ void ICACHE_RAM_ATTR Twi::onTwipEvent(uint8_t status)
     }
 }
 
-void Twi::twi_scl_valley(void)
-{
-    SCL_LOW(twi_scl);
-    busywait(twi_dcount);
-    SCL_HIGH(twi_scl);
-    WAIT_CLOCK_STRETCH();
-}
-
 void ICACHE_RAM_ATTR Twi::onTimer(void *unused)
 {
     (void)unused;