From c6938e2048fb7a91ad4bf987717d822c8588011b Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 3 Sep 2023 23:15:33 +0200 Subject: [PATCH] Reduce IRAM consumption of HDMI CEC to 1453 bytes (#19452) * Reduce IRAM consumption of HDMI CEC to 1453 bytes * Add changelog --- CHANGELOG.md | 1 + tasmota/my_user_config.h | 2 +- .../xdrv_70_0_hdmi_cec.ino | 46 +++++++++---------- 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5d931f96128..19a180a6684e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. ### Changed - Berry fast_loop is now called every 5ms whatever the Sleep value +- Reduce IRAM consumption of HDMI CEC to 1453 bytes ### Fixed - PCF8574 mode 1 with base relays exception 3/28 regression from v12.4.0.4 (#19408) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 191df8c9d613..d35faf0f2a90 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -784,7 +784,7 @@ #endif // USE_SPI // -- One wire sensors ---------------------------- -// #define USE_HDMI_CEC // Add support for HDMI CEC bus (+7k code) +// #define USE_HDMI_CEC // Add support for HDMI CEC bus (+7k code, 1456 bytes IRAM) // -- Serial sensors ------------------------------ //#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_70_0_hdmi_cec.ino b/tasmota/tasmota_xdrv_driver/xdrv_70_0_hdmi_cec.ino index b2c044165243..dcc05fbaa13b 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_70_0_hdmi_cec.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_70_0_hdmi_cec.ino @@ -39,7 +39,6 @@ #endif volatile uint32_t cec_isr_count = 0; -volatile uint32_t cec_isr_rcv_count = 0; /*********************************************************************************************\ * Ring buffer class that allows the ISR to publish logs and messages to the main event loop @@ -91,31 +90,35 @@ public: // returns true if ok, false if full bool IRAM_ATTR push(const volatile uint8_t *buf, uint8_t len, CEC_MSG_TYPE type, bool ack) { // AddLog(LOG_LEVEL_INFO, ">>>: push len=%i type=%i ack=%i", len, type, ack); - if (_msg[_cur_idx].type != MSG_EMPTY) { + uint32_t cur_idx = _cur_idx; // read only once the volatile value + CEC_msg_t *msg = &_msg[cur_idx]; + if (msg->type != MSG_EMPTY) { return false; } - memmove(_msg[_cur_idx].buf, (uint8_t*) buf, CEC_BUF_SIZE); - _msg[_cur_idx].ack = ack; - _msg[_cur_idx].len = len; - _msg[_cur_idx].type = type; - _cur_idx = (_cur_idx + 1) % CEC_RING_SIZE; + memmove(&msg->buf, (uint8_t*) buf, CEC_BUF_SIZE); + msg->ack = ack; + msg->len = len; + msg->type = type; + _cur_idx = (cur_idx + 1) % CEC_RING_SIZE; return true; } // returns true if ok, false if full bool IRAM_ATTR log(uint32_t timing_expected_low, uint32_t timing_expected_high, uint32_t timing, uint16_t code, uint8_t state, bool line) { #ifdef HDMI_DEBUG - if (_msg[_cur_idx].type != MSG_EMPTY) { + uint32_t cur_idx = _cur_idx; // read only once the volatile value + CEC_msg_t *msg = &_msg[cur_idx]; + if (msg->type != MSG_EMPTY) { return false; } - _msg[_cur_idx].type = MSG_LOG; - _msg[_cur_idx].timing_expected_low = timing_expected_low; - _msg[_cur_idx].timing_expected_high = timing_expected_high; - _msg[_cur_idx].timing = timing; - _msg[_cur_idx].code = code; - _msg[_cur_idx].state = state; - _msg[_cur_idx].line = line; - _cur_idx = (_cur_idx + 1) % CEC_RING_SIZE; + msg->type = MSG_LOG; + msg->timing_expected_low = timing_expected_low; + msg->timing_expected_high = timing_expected_high; + msg->timing = timing; + msg->code = code; + msg->state = state; + msg->line = line; + _cur_idx = (cur_idx + 1) % CEC_RING_SIZE; #endif return true; } @@ -248,7 +251,7 @@ public: void checkMessages(); // check regularly for mailbox // signal to Tasmota to exit the normal sleep and trigger a new tick event in the next millisecond void enableISR(void); - void IRAM_ATTR serviceGpioISR(void); // handle the ISR on the CEC GPIO + inline void IRAM_ATTR serviceGpioISR(void) { runReceiveISR(); }; // handle the ISR on the CEC GPIO bool transmitRaw(const unsigned char* buffer, unsigned int count); // Getters @@ -474,7 +477,7 @@ void CEC_Device::start(void) { /// /// The state machine works in blocking mode /// -void IRAM_ATTR CEC_Device::runTransmit() { +void CEC_Device::runTransmit() { if (!_xmit_wait_ms) { // we haven't waited for the signal to stabilize yet // compute the number of milliseconds to wait for in fast loop @@ -716,7 +719,6 @@ void IRAM_ATTR CEC_Device::runTransmit() { void IRAM_ATTR CEC_Device::runReceiveISR() { if (isTransmitting()) { return; } // ignore any interrupt caused or during active transmission - cec_isr_rcv_count += 1; // update timing information for new iteration uint32_t now = micros(); if (!now) { now = 1; } // avoid now == 0 which has a special meaning @@ -1055,12 +1057,6 @@ void CEC_Device::enableISR(void) { } } -// Service gpio ISR -void IRAM_ATTR CEC_Device::serviceGpioISR(void) { - cec_isr_count += 1; - runReceiveISR(); -} - /*********************************************************************************************\ * General methods \*********************************************************************************************/