Skip to content

Commit 3b276ea

Browse files
committed
esp_codec_dev: Fixed lock issue for multiple i2s if
1 parent fef7059 commit 3b276ea

File tree

3 files changed

+74
-29
lines changed

3 files changed

+74
-29
lines changed

components/esp_codec_dev/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## v1.5.2
4+
5+
### Bug Fixed
6+
7+
- Fixed race condition when duplex I2S used by multiple data interface and run open in parallel.
8+
39
## v1.5.1
410

511
### Bug Fixed

components/esp_codec_dev/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: 1.5.1
1+
version: 1.5.2
22
description: Audio codec device support for Espressif SOC
33
url: https://github.com/espressif/esp-adf/tree/master/components/esp_codec_dev
44

components/esp_codec_dev/platform/audio_codec_data_i2s.c

Lines changed: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,83 @@ typedef struct {
3838
esp_codec_dev_sample_info_t in_fs;
3939
esp_codec_dev_sample_info_t out_fs;
4040
esp_codec_dev_sample_info_t fs;
41-
esp_codec_dev_mutex_handle_t lock;
4241
} i2s_data_t;
4342

4443
typedef struct i2s_data_keep_t i2s_data_keep_t;
4544
struct i2s_data_keep_t {
46-
i2s_data_t *i2s_data;
47-
i2s_data_keep_t *next;
45+
i2s_data_t *i2s_data;
46+
esp_codec_dev_mutex_handle_t mutex;
47+
i2s_data_keep_t *next;
4848
};
4949

5050
static i2s_data_keep_t *i2s_data_list = NULL;
5151

52+
static esp_codec_dev_mutex_handle_t try_alloc_mutex(uint8_t port)
53+
{
54+
i2s_data_keep_t *cur = i2s_data_list;
55+
while (cur != NULL) {
56+
if (cur->i2s_data->port == port) {
57+
return cur->mutex;
58+
}
59+
cur = cur->next;
60+
}
61+
return esp_codec_dev_mutex_create();
62+
}
63+
64+
static esp_codec_dev_mutex_handle_t get_mutex(i2s_data_t *i2s_data)
65+
{
66+
i2s_data_keep_t *cur = i2s_data_list;
67+
while (cur != NULL) {
68+
if (cur->i2s_data == i2s_data) {
69+
return cur->mutex;
70+
}
71+
cur = cur->next;
72+
}
73+
return NULL;
74+
}
75+
76+
static void try_free_mutex(uint8_t port, esp_codec_dev_mutex_handle_t mutex)
77+
{
78+
uint8_t ref_count = 0;
79+
i2s_data_keep_t *cur = i2s_data_list;
80+
while (cur != NULL) {
81+
if (cur->i2s_data->port == port) {
82+
ref_count++;
83+
}
84+
cur = cur->next;
85+
}
86+
if (ref_count == 0) {
87+
esp_codec_dev_mutex_destroy(mutex);
88+
}
89+
}
90+
91+
static void _i2s_lock(i2s_data_t *i2s_data, const char *func)
92+
{
93+
esp_codec_dev_mutex_handle_t mutex = get_mutex(i2s_data);
94+
if (mutex) {
95+
int ret = esp_codec_dev_mutex_lock(mutex, DEFAULT_WAIT_TIMEOUT);
96+
if (ret != ESP_CODEC_DEV_OK) {
97+
ESP_LOGE(TAG, "Lock failed in %s", func);
98+
}
99+
}
100+
}
101+
102+
static void _i2s_unlock(i2s_data_t *i2s_data)
103+
{
104+
esp_codec_dev_mutex_handle_t mutex = get_mutex(i2s_data);
105+
if (mutex) {
106+
esp_codec_dev_mutex_unlock(mutex);
107+
}
108+
}
109+
52110
static void add_to_keeper(i2s_data_t *i2s_data)
53111
{
54112
i2s_data_keep_t *keep_info = (i2s_data_keep_t *) calloc(1, sizeof(i2s_data_keep_t));
55113
if (keep_info == NULL) {
56114
ESP_LOGE(TAG, "Out of memory for keeper");
57115
return;
58116
}
117+
keep_info->mutex = try_alloc_mutex(i2s_data->port);
59118
keep_info->i2s_data = i2s_data;
60119
if (i2s_data_list == NULL) {
61120
i2s_data_list = keep_info;
@@ -76,6 +135,7 @@ static void remove_from_keeper(i2s_data_t *i2s_data)
76135
} else {
77136
pre->next = cur->next;
78137
}
138+
try_free_mutex(i2s_data->port, cur->mutex);
79139
free(cur);
80140
break;
81141
}
@@ -408,9 +468,6 @@ static int _i2s_data_open(const audio_codec_data_if_t *h, void *data_cfg, int cf
408468
i2s_data->port = i2s_cfg->port;
409469
i2s_data->out_handle = i2s_cfg->tx_handle;
410470
i2s_data->in_handle = i2s_cfg->rx_handle;
411-
if (i2s_data->out_handle != NULL && i2s_data->in_handle != NULL) {
412-
i2s_data->lock = esp_codec_dev_mutex_create();
413-
}
414471
add_to_keeper(i2s_data);
415472
return ESP_CODEC_DEV_OK;
416473
}
@@ -434,12 +491,7 @@ static int _i2s_data_enable(const audio_codec_data_if_t *h, esp_codec_dev_type_t
434491
return ESP_CODEC_DEV_WRONG_STATE;
435492
}
436493
int ret = ESP_CODEC_DEV_OK;
437-
if (i2s_data->lock) {
438-
ret = esp_codec_dev_mutex_lock(i2s_data->lock, DEFAULT_WAIT_TIMEOUT);
439-
if (ret != ESP_CODEC_DEV_OK) {
440-
ESP_LOGW(TAG, "Enable wait lock timeout");
441-
}
442-
}
494+
_i2s_lock(i2s_data, __func__);
443495
if (dev_type == ESP_CODEC_DEV_TYPE_IN_OUT) {
444496
ret = _i2s_drv_enable(i2s_data, true, enable);
445497
ret = _i2s_drv_enable(i2s_data, false, enable);
@@ -486,9 +538,7 @@ static int _i2s_data_enable(const audio_codec_data_if_t *h, esp_codec_dev_type_t
486538
if (dev_type & ESP_CODEC_DEV_TYPE_OUT) {
487539
i2s_data->out_enable = enable;
488540
}
489-
if (i2s_data->lock) {
490-
esp_codec_dev_mutex_unlock(i2s_data->lock);
491-
}
541+
_i2s_unlock(i2s_data);
492542
return ret;
493543
}
494544

@@ -524,12 +574,7 @@ static int _i2s_data_set_fmt(const audio_codec_data_if_t *h, esp_codec_dev_type_
524574
}
525575
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
526576
int ret;
527-
if (i2s_data->lock) {
528-
ret = esp_codec_dev_mutex_lock(i2s_data->lock, DEFAULT_WAIT_TIMEOUT);
529-
if (ret != ESP_CODEC_DEV_OK) {
530-
ESP_LOGW(TAG, "Set format wait lock timeout");
531-
}
532-
}
577+
_i2s_lock(i2s_data, __func__);
533578
// disable internally
534579
if (dev_type & ESP_CODEC_DEV_TYPE_OUT) {
535580
_i2s_drv_enable(i2s_data, true, false);
@@ -548,9 +593,7 @@ static int _i2s_data_set_fmt(const audio_codec_data_if_t *h, esp_codec_dev_type_
548593
} else {
549594
ret = check_fs_compatible(i2s_data, dev_type & ESP_CODEC_DEV_TYPE_OUT ? true : false, fs);
550595
}
551-
if (i2s_data->lock) {
552-
esp_codec_dev_mutex_unlock(i2s_data->lock);
553-
}
596+
_i2s_unlock(i2s_data);
554597
return ret;
555598
#else
556599
// When use multichannel data
@@ -638,10 +681,6 @@ static int _i2s_data_close(const audio_codec_data_if_t *h)
638681
memset(&i2s_data->fs, 0, sizeof(esp_codec_dev_sample_info_t));
639682
memset(&i2s_data->in_fs, 0, sizeof(esp_codec_dev_sample_info_t));
640683
memset(&i2s_data->out_fs, 0, sizeof(esp_codec_dev_sample_info_t));
641-
if (i2s_data->lock) {
642-
esp_codec_dev_mutex_destroy(i2s_data->lock);
643-
i2s_data->lock = NULL;
644-
}
645684
i2s_data->is_open = false;
646685
remove_from_keeper(i2s_data);
647686
return ESP_CODEC_DEV_OK;

0 commit comments

Comments
 (0)