rmt: fix memory leak in the legacy driver

Closes https://github.com/espressif/esp-idf/issues/10173
This commit is contained in:
morris 2022-11-14 18:46:58 +08:00
parent 9d56ce3556
commit 6c8807e789
3 changed files with 7 additions and 10 deletions

View File

@ -64,7 +64,7 @@ typedef struct {
portMUX_TYPE rmt_spinlock; // Mutex lock for protecting concurrent register/unregister of RMT channels' ISR portMUX_TYPE rmt_spinlock; // Mutex lock for protecting concurrent register/unregister of RMT channels' ISR
rmt_isr_handle_t rmt_driver_intr_handle; rmt_isr_handle_t rmt_driver_intr_handle;
rmt_tx_end_callback_t rmt_tx_end_callback;// Event called when transmission is ended 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; bool rmt_module_enabled;
uint32_t synchro_channel_mask; // Bitmap of channels already added in the synchronous group uint32_t synchro_channel_mask; // Bitmap of channels already added in the synchronous group
} rmt_contex_t; } rmt_contex_t;
@ -924,7 +924,7 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel)
{ {
esp_err_t err = ESP_OK; 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(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) { if (p_rmt_obj[channel] == NULL) {
return ESP_OK; 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)); _lock_acquire_recursive(&(rmt_contex.rmt_driver_isr_lock));
rmt_contex.rmt_driver_channels &= ~BIT(channel); 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(); rmt_module_disable();
// all channels have driver disabled // all channels have driver disabled
err = rmt_isr_deregister(rmt_contex.rmt_driver_intr_handle); 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)); _lock_release_recursive(&(rmt_contex.rmt_driver_isr_lock));
if (err != ESP_OK) {
return err;
}
if (p_rmt_obj[channel]->tx_sem) { if (p_rmt_obj[channel]->tx_sem) {
vSemaphoreDelete(p_rmt_obj[channel]->tx_sem); vSemaphoreDelete(p_rmt_obj[channel]->tx_sem);
p_rmt_obj[channel]->tx_sem = NULL; 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]); free(p_rmt_obj[channel]);
p_rmt_obj[channel] = NULL; 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_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(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; esp_err_t err = ESP_OK;

View File

@ -212,11 +212,14 @@ TEST_CASE("RMT multiple channels", "[rmt]")
TEST_CASE("RMT install/uninstall test", "[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); 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)); TEST_ESP_OK(rmt_config(&tx_cfg));
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
TEST_ESP_OK(rmt_driver_install(tx_cfg.channel, 1000, 0)); 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));
} }
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); rmt_config_t rx_cfg = RMT_DEFAULT_CONFIG_RX(RMT_DATA_IO, RMT_RX_CHANNEL_ENCODING_START);
TEST_ESP_OK(rmt_config(&rx_cfg)); TEST_ESP_OK(rmt_config(&rx_cfg));
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {

View File

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