diff --git a/libraries/ESP_I2S/src/ESP_I2S.cpp b/libraries/ESP_I2S/src/ESP_I2S.cpp index 6bf8089e48a..e2c6d670b9b 100644 --- a/libraries/ESP_I2S/src/ESP_I2S.cpp +++ b/libraries/ESP_I2S/src/ESP_I2S.cpp @@ -192,6 +192,7 @@ static esp_err_t i2s_channel_read_16_stereo_to_mono(i2s_chan_handle_t handle, ch I2SClass::I2SClass() { last_error = ESP_OK; + _mode = I2S_MODE_MAX; // Initialize to invalid mode to indicate I2S not started tx_chan = NULL; tx_sample_rate = 0; @@ -239,7 +240,9 @@ I2SClass::~I2SClass() { bool I2SClass::i2sDetachBus(void *bus_pointer) { I2SClass *bus = (I2SClass *)bus_pointer; - if (bus->tx_chan != NULL || bus->tx_chan != NULL) { + // Only call end() if I2S has been initialized (begin() was called) + // _mode is set to I2S_MODE_MAX in constructor and to a valid mode in begin() + if (bus->_mode < I2S_MODE_MAX) { bus->end(); } return true; @@ -703,6 +706,16 @@ bool I2SClass::begin(i2s_mode_t mode, uint32_t rate, i2s_data_bit_width_t bits_c } bool I2SClass::end() { + // Check if already ended to prevent recursion + if (_mode >= I2S_MODE_MAX) { + return true; + } + + // Save mode and reset it BEFORE clearing pins to prevent recursive calls + // When perimanClearPinBus() is called, it may trigger i2sDetachBus() again + i2s_mode_t mode = _mode; + _mode = I2S_MODE_MAX; + if (tx_chan != NULL) { I2S_ERROR_CHECK_RETURN_FALSE(i2s_channel_disable(tx_chan)); I2S_ERROR_CHECK_RETURN_FALSE(i2s_del_channel(tx_chan)); @@ -720,7 +733,7 @@ bool I2SClass::end() { } //Peripheral manager deinit used pins - switch (_mode) { + switch (mode) { case I2S_MODE_STD: #if SOC_I2S_SUPPORTS_TDM case I2S_MODE_TDM: diff --git a/tests/validation/gpio/gpio.ino b/tests/validation/gpio/gpio.ino index b0c3f7ec0bd..20c62fcd351 100644 --- a/tests/validation/gpio/gpio.ino +++ b/tests/validation/gpio/gpio.ino @@ -13,7 +13,6 @@ volatile int interruptCounter = 0; volatile bool interruptFlag = false; -volatile unsigned long lastInterruptTime = 0; // Variables for interrupt with argument test volatile int argInterruptCounter = 0; @@ -34,7 +33,6 @@ void waitForSyncAck(const String &token = "OK") { void setUp(void) { interruptCounter = 0; interruptFlag = false; - lastInterruptTime = 0; argInterruptCounter = 0; argInterruptFlag = false; receivedArg = 0; @@ -43,22 +41,14 @@ void setUp(void) { void tearDown(void) {} void IRAM_ATTR buttonISR() { - unsigned long currentTime = millis(); - if (currentTime - lastInterruptTime > 50) { - interruptCounter = interruptCounter + 1; - interruptFlag = true; - lastInterruptTime = currentTime; - } + interruptCounter = interruptCounter + 1; + interruptFlag = true; } void IRAM_ATTR buttonISRWithArg(void *arg) { - unsigned long currentTime = millis(); - if (currentTime - lastInterruptTime > 50) { - argInterruptCounter = argInterruptCounter + 1; - argInterruptFlag = true; - receivedArg = *(int *)arg; - lastInterruptTime = currentTime; - } + argInterruptCounter = argInterruptCounter + 1; + argInterruptFlag = true; + receivedArg = *(int *)arg; } void test_read_basic(void) { diff --git a/tests/validation/i2c_master/i2c_master.ino b/tests/validation/i2c_master/i2c_master.ino index 41e7d2ae5f9..287f4dca76a 100644 --- a/tests/validation/i2c_master/i2c_master.ino +++ b/tests/validation/i2c_master/i2c_master.ino @@ -108,7 +108,7 @@ void ds1307_get_time(uint8_t *sec, uint8_t *min, uint8_t *hour, uint8_t *day, ui void ds1307_set_time(uint8_t sec, uint8_t min, uint8_t hour, uint8_t day, uint8_t month, uint16_t year) { Wire.beginTransmission(DS1307_ADDR); Wire.write(0x00); - Wire.write(DEC2BCD(sec)); + Wire.write(DEC2BCD(sec) | 0x80); //Set halt bit to stop clock Wire.write(DEC2BCD(min)); Wire.write(DEC2BCD(hour)); Wire.write(DEC2BCD(0)); //Ignore day of week @@ -212,6 +212,22 @@ void change_clock() { TEST_ASSERT_EQUAL(start_day, read_day); TEST_ASSERT_EQUAL(start_month, read_month); TEST_ASSERT_EQUAL(start_year, read_year); + + //Run clock for 5 seconds to check that we can write + ds1307_start(); + delay(5000); + ds1307_stop(); + + //Get time + ds1307_get_time(&read_sec, &read_min, &read_hour, &read_day, &read_month, &read_year); + + //Check time + TEST_ASSERT_NOT_EQUAL(start_sec, read_sec); //Seconds should have changed + TEST_ASSERT_EQUAL(start_min, read_min); + TEST_ASSERT_EQUAL(start_hour, read_hour); + TEST_ASSERT_EQUAL(start_day, read_day); + TEST_ASSERT_EQUAL(start_month, read_month); + TEST_ASSERT_EQUAL(start_year, read_year); } void swap_pins() { diff --git a/tests/validation/periman/periman.ino b/tests/validation/periman/periman.ino index 4e727bac7a3..2b89e3529fd 100644 --- a/tests/validation/periman/periman.ino +++ b/tests/validation/periman/periman.ino @@ -10,6 +10,8 @@ * - ETH: ETH requires a ethernet port to be connected before the pins are attached */ +#include + #if SOC_I2S_SUPPORTED #include "ESP_I2S.h" #endif @@ -71,7 +73,10 @@ void setup_test(String test_name, int8_t rx_pin = UART1_RX_DEFAULT, int8_t tx_pi pinMode(uart1_rx_pin, INPUT_PULLUP); pinMode(uart1_tx_pin, OUTPUT); + // Ensure Serial1 is initialized and callback is set (in case it was terminated previously) Serial1.setPins(uart1_rx_pin, uart1_tx_pin); + Serial1.begin(115200); + Serial1.onReceive(onReceive_cb); uart_internal_loopback(1, uart1_rx_pin); delay(100); log_v("Running %s test", test_name.c_str()); @@ -86,12 +91,16 @@ void teardown_test(void) { Serial1.print(current_test); Serial1.println(" test: This should not be printed"); Serial1.flush(); - - Serial1.setPins(uart1_rx_pin, uart1_tx_pin); - uart_internal_loopback(1, uart1_rx_pin); - delay(100); } + // Even if test didn't execute, ensure Serial1 is initialized + // (in case it was terminated by a previous test or setup issue) + Serial1.setPins(uart1_rx_pin, uart1_tx_pin); + Serial1.begin(115200); + Serial1.onReceive(onReceive_cb); + uart_internal_loopback(1, uart1_rx_pin); + delay(100); + Serial1.print(current_test); Serial1.println(" test: This should be printed"); Serial1.flush();