Skip to content

Commit

Permalink
Fix ESP32C3 relay toggle on restart
Browse files Browse the repository at this point in the history
Fix ESP32C3 relay toggle on restart (arendst#20030)
  • Loading branch information
arendst committed Nov 17, 2023
1 parent 040e25a commit b02a66a
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 34 deletions.
14 changes: 0 additions & 14 deletions tasmota/tasmota_support/support.ino
Original file line number Diff line number Diff line change
Expand Up @@ -1442,30 +1442,16 @@ void SetPin(uint32_t lpin, uint32_t gpio) {
TasmotaGlobal.gpio_pin[lpin] = gpio;
}

#ifdef CONFIG_IDF_TARGET_ESP32C3
#include "driver/gpio.h" // Include needed for Arduino 3
#endif

void DigitalWrite(uint32_t gpio_pin, uint32_t index, uint32_t state) {
static uint32_t pinmode_init[2] = { 0 }; // Pins 0 to 63 !!!

if (PinUsed(gpio_pin, index)) {
uint32_t pin = Pin(gpio_pin, index) & 0x3F; // Fix possible overflow over 63 gpios
#ifdef CONFIG_IDF_TARGET_ESP32C3
// if (GPIO_REL1 == gpio_pin) {
gpio_hold_dis((gpio_num_t)pin); // Allow state change
// }
#endif
if (!bitRead(pinmode_init[pin / 32], pin % 32)) {
bitSet(pinmode_init[pin / 32], pin % 32);
pinMode(pin, OUTPUT);
}
digitalWrite(pin, state &1);
#ifdef CONFIG_IDF_TARGET_ESP32C3
if (GPIO_REL1 == gpio_pin) {
gpio_hold_en((gpio_num_t)pin); // Retain the state when the chip or system is reset, for example, when watchdog time-out or Deep-sleep
}
#endif
}
}

Expand Down
38 changes: 38 additions & 0 deletions tasmota/tasmota_support/support_esp32.ino
Original file line number Diff line number Diff line change
Expand Up @@ -978,4 +978,42 @@ uint32_t HwRandom(void) {
#endif // ESP_IDF_VERSION_MAJOR >= 5
}

/********************************************************************************************/
// Since ESP-IDF 4.4, GPIO matrix or I/O is not reset during a restart
// and GPIO configuration can get stuck because of leftovers
//
// This patched version of pinMode forces a full GPIO reset before setting new mode
//
#include "driver/gpio.h"

extern "C" void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode);

extern "C" void ARDUINO_ISR_ATTR pinMode(uint8_t pin, uint8_t mode) {
gpio_reset_pin((gpio_num_t)pin);
__pinMode(pin, mode);
#ifdef CONFIG_IDF_TARGET_ESP32C3
// See GpioForceHoldRelay() below
gpio_hold_dis((gpio_num_t)pin); // Allow state change
#endif
}

#ifdef CONFIG_IDF_TARGET_ESP32C3
void GpioForceHoldRelay(void) {
// Only ESP32-C3 toggles outputs on restart unless gpio_hold_en() is called before restart
// Retain the state when the chip or system is reset, for example, when watchdog time-out or Deep-sleep

// gpio_force_hold_all(); // This will hold flash/serial too so do not use

uint16_t real_gpio = GPIO_REL1 << 5;
uint16_t mask = 0xFFE0;
for (uint32_t i = 0; i < nitems(TasmotaGlobal.gpio_pin); i++) {
if ((TasmotaGlobal.gpio_pin[i] & mask) == real_gpio) {
gpio_hold_en((gpio_num_t)i); // Retain the state when the chip or system is reset, for example, when watchdog time-out or Deep-sleep
}
}
}
#endif

/********************************************************************************************/

#endif // ESP32
18 changes: 0 additions & 18 deletions tasmota/tasmota_support/support_tasmota.ino
Original file line number Diff line number Diff line change
Expand Up @@ -1916,24 +1916,6 @@ void TasConsoleInput(void) {

/********************************************************************************************/

#ifdef ESP32
// Since ESP-IDF 4.4, GPIO matrix or I/O is not reset during a restart
// and GPIO configuration can get stuck because of leftovers
//
// This patched version of pinMode forces a full GPIO reset before setting new mode
//
#include "driver/gpio.h"

extern "C" void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode);

extern "C" void ARDUINO_ISR_ATTR pinMode(uint8_t pin, uint8_t mode) {
gpio_reset_pin((gpio_num_t)pin);
__pinMode(pin, mode);
}
#endif

/********************************************************************************************/

void GpioInit(void)
{
if (!ValidModule(Settings->module)) {
Expand Down
7 changes: 5 additions & 2 deletions tasmota/tasmota_support/support_wifi.ino
Original file line number Diff line number Diff line change
Expand Up @@ -1149,12 +1149,15 @@ void WifiDisable(void) {
TasmotaGlobal.global_state.wifi_down = 1;
}

void EspRestart(void)
{
void EspRestart(void) {
ResetPwm();
WifiShutdown(true);
CrashDumpClear(); // Clear the stack dump in RTC

#ifdef CONFIG_IDF_TARGET_ESP32C3
GpioForceHoldRelay(); // Retain the state when the chip or system is reset, for example, when watchdog time-out or Deep-sleep
#endif // CONFIG_IDF_TARGET_ESP32C3

if (TasmotaGlobal.restart_halt) { // Restart 2
while (1) {
OsWatchLoop(); // Feed OsWatch timer to prevent restart
Expand Down

0 comments on commit b02a66a

Please sign in to comment.