Quellcode durchsuchen

Merge branch 'bugfix/legacy_rmt_resource_leak' into 'master'

rmt: fix memory leak in the legacy driver

Closes IDFGH-8732 and IDF-5941

See merge request espressif/esp-idf!21084
morris vor 3 Jahren
Ursprung
Commit
dcaa753f37

+ 4 - 9
components/driver/deprecated/rmt_legacy.c

@@ -64,7 +64,7 @@ typedef struct {
     portMUX_TYPE rmt_spinlock; // Mutex lock for protecting concurrent register/unregister of RMT channels' ISR
     rmt_isr_handle_t rmt_driver_intr_handle;
     rmt_tx_end_callback_t rmt_tx_end_callback;// Event called when transmission is ended
-    uint8_t rmt_driver_channels; // Bitmask of installed drivers' channels
+    uint8_t rmt_driver_channels; // Bitmask of installed drivers' channels, used to protect concurrent register/unregister of RMT channels' ISR
     bool rmt_module_enabled;
     uint32_t synchro_channel_mask; // Bitmap of channels already added in the synchronous group
 } rmt_contex_t;
@@ -924,7 +924,7 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel)
 {
     esp_err_t err = ESP_OK;
     ESP_RETURN_ON_FALSE(channel < RMT_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR);
-    ESP_RETURN_ON_FALSE(rmt_contex.rmt_driver_channels & BIT(channel), ESP_ERR_INVALID_STATE, TAG, "No RMT driver for this channel");
+    // we allow to call this uninstall function on the same channel for multiple times
     if (p_rmt_obj[channel] == NULL) {
         return ESP_OK;
     }
@@ -944,7 +944,7 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel)
 
     _lock_acquire_recursive(&(rmt_contex.rmt_driver_isr_lock));
     rmt_contex.rmt_driver_channels &= ~BIT(channel);
-    if (rmt_contex.rmt_driver_channels == 0) {
+    if (rmt_contex.rmt_driver_channels == 0 && rmt_contex.rmt_driver_intr_handle) {
         rmt_module_disable();
         // all channels have driver disabled
         err = rmt_isr_deregister(rmt_contex.rmt_driver_intr_handle);
@@ -952,10 +952,6 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel)
     }
     _lock_release_recursive(&(rmt_contex.rmt_driver_isr_lock));
 
-    if (err != ESP_OK) {
-        return err;
-    }
-
     if (p_rmt_obj[channel]->tx_sem) {
         vSemaphoreDelete(p_rmt_obj[channel]->tx_sem);
         p_rmt_obj[channel]->tx_sem = NULL;
@@ -981,13 +977,12 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel)
 
     free(p_rmt_obj[channel]);
     p_rmt_obj[channel] = NULL;
-    return ESP_OK;
+    return err;
 }
 
 esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr_alloc_flags)
 {
     ESP_RETURN_ON_FALSE(channel < RMT_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR);
-    ESP_RETURN_ON_FALSE((rmt_contex.rmt_driver_channels & BIT(channel)) == 0, ESP_ERR_INVALID_STATE, TAG, "RMT driver already installed for channel");
 
     esp_err_t err = ESP_OK;
 

+ 3 - 0
components/driver/test_apps/legacy_rmt_driver/main/test_legacy_rmt.c

@@ -212,11 +212,14 @@ TEST_CASE("RMT multiple channels", "[rmt]")
 TEST_CASE("RMT install/uninstall test", "[rmt]")
 {
     rmt_config_t tx_cfg = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, RMT_TX_CHANNEL_ENCODING_END);
+    // uninstall function is allowed to be called at any time
+    TEST_ESP_OK(rmt_driver_uninstall(tx_cfg.channel));
     TEST_ESP_OK(rmt_config(&tx_cfg));
     for (int i = 0; i < 100; i++) {
         TEST_ESP_OK(rmt_driver_install(tx_cfg.channel, 1000, 0));
         TEST_ESP_OK(rmt_driver_uninstall(tx_cfg.channel));
     }
+    TEST_ESP_OK(rmt_driver_uninstall(tx_cfg.channel));
     rmt_config_t rx_cfg = RMT_DEFAULT_CONFIG_RX(RMT_DATA_IO, RMT_RX_CHANNEL_ENCODING_START);
     TEST_ESP_OK(rmt_config(&rx_cfg));
     for (int i = 0; i < 100; i++) {

+ 0 - 1
docs/docs_not_updated/esp32c6.txt

@@ -122,7 +122,6 @@ api-reference/peripherals/spi_master
 api-reference/peripherals/index
 api-reference/peripherals/sdmmc_host
 api-reference/peripherals/uart
-api-reference/peripherals/rmt
 api-reference/kconfig
 api-reference/network
 api-reference/network/esp_openthread