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;