Skip to content

Commit 367b5f2

Browse files
committed
drivers: i2s: esp32: fix last block loss
Avoids erroneous memory block freeing when stopping transfers Signed-off-by: Marcio Ribeiro <[email protected]>
1 parent 86a46c4 commit 367b5f2

File tree

1 file changed

+28
-51
lines changed

1 file changed

+28
-51
lines changed

drivers/i2s/i2s_esp32.c

Lines changed: 28 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ struct i2s_esp32_stream_data {
5555
struct i2s_config i2s_cfg;
5656
void *mem_block;
5757
size_t mem_block_len;
58-
bool last_block;
5958
bool stop_without_draining;
6059
struct k_msgq queue;
6160
struct intr_handle_data_t *irq_handle;
@@ -175,6 +174,18 @@ static void i2s_esp32_rx_callback(void *arg, int status)
175174
const struct i2s_esp32_stream *stream = &dev_cfg->rx;
176175
int err;
177176

177+
if (!stream->data->dma_pending) {
178+
return;
179+
}
180+
181+
stream->data->dma_pending = false;
182+
183+
if (stream->data->mem_block == NULL) {
184+
LOG_ERR("RX mem_block NULL");
185+
stream->data->state = I2S_STATE_ERROR;
186+
goto rx_disable;
187+
}
188+
178189
#if SOC_GDMA_SUPPORTED
179190
if (status < 0) {
180191
#else
@@ -185,16 +196,6 @@ static void i2s_esp32_rx_callback(void *arg, int status)
185196
goto rx_disable;
186197
}
187198

188-
if (stream->data->mem_block == NULL) {
189-
if (stream->data->state != I2S_STATE_READY) {
190-
stream->data->state = I2S_STATE_ERROR;
191-
LOG_ERR("RX mem_block NULL");
192-
goto rx_disable;
193-
} else {
194-
return;
195-
}
196-
}
197-
198199
#if SOC_GDMA_SUPPORTED
199200
const i2s_hal_context_t *hal = &(dev_cfg->hal);
200201
uint16_t chunk_len;
@@ -339,11 +340,8 @@ static void i2s_esp32_rx_stop_transfer(const struct device *dev)
339340
i2s_hal_clear_intr_status(hal, I2S_INTR_MAX);
340341
#endif /* SOC_GDMA_SUPPORTED */
341342

342-
if (stream->data->mem_block != NULL) {
343-
k_mem_slab_free(stream->data->i2s_cfg.mem_slab, stream->data->mem_block);
344-
stream->data->mem_block = NULL;
345-
stream->data->mem_block_len = 0;
346-
}
343+
stream->data->mem_block = NULL;
344+
stream->data->mem_block_len = 0;
347345
}
348346

349347
#endif /* I2S_ESP32_IS_DIR_EN(rx) */
@@ -361,7 +359,6 @@ static void i2s_esp32_tx_callback(void *arg, int status)
361359
const struct i2s_esp32_cfg *const dev_cfg = dev->config;
362360
const struct i2s_esp32_stream *stream = &dev_cfg->tx;
363361
struct queue_item item;
364-
void *mem_block_tmp;
365362
int err;
366363

367364
if (!stream->data->dma_pending) {
@@ -370,6 +367,14 @@ static void i2s_esp32_tx_callback(void *arg, int status)
370367

371368
stream->data->dma_pending = false;
372369

370+
if (stream->data->mem_block == NULL) {
371+
LOG_ERR("TX mem_block NULL");
372+
stream->data->state = I2S_STATE_ERROR;
373+
goto tx_disable;
374+
}
375+
376+
k_mem_slab_free(stream->data->i2s_cfg.mem_slab, stream->data->mem_block);
377+
373378
#if SOC_GDMA_SUPPORTED
374379
if (status < 0) {
375380
#else
@@ -380,41 +385,21 @@ static void i2s_esp32_tx_callback(void *arg, int status)
380385
goto tx_disable;
381386
}
382387

383-
if (stream->data->mem_block == NULL) {
384-
if (stream->data->state != I2S_STATE_READY) {
385-
stream->data->state = I2S_STATE_ERROR;
386-
LOG_ERR("TX mem_block NULL");
387-
goto tx_disable;
388-
} else {
389-
return;
390-
}
391-
}
392-
393388
if (stream->data->state == I2S_STATE_STOPPING) {
394-
if (k_msgq_num_used_get(&stream->data->queue) == 0) {
395-
stream->data->state = I2S_STATE_READY;
396-
goto tx_disable;
397-
} else if (stream->data->stop_without_draining == true) {
398-
stream->conf->queue_drop(stream);
389+
if (k_msgq_num_used_get(&stream->data->queue) == 0 ||
390+
stream->data->stop_without_draining == true) {
399391
stream->data->state = I2S_STATE_READY;
400392
goto tx_disable;
401393
}
402394
}
403395

404-
if (stream->data->last_block) {
405-
stream->data->state = I2S_STATE_READY;
406-
goto tx_disable;
407-
}
408-
409396
err = k_msgq_get(&stream->data->queue, &item, K_NO_WAIT);
410397
if (err < 0) {
411398
stream->data->state = I2S_STATE_ERROR;
412399
LOG_ERR("TX queue empty: %d", err);
413400
goto tx_disable;
414401
}
415402

416-
mem_block_tmp = stream->data->mem_block;
417-
418403
stream->data->mem_block = item.buffer;
419404
stream->data->mem_block_len = item.size;
420405

@@ -425,8 +410,6 @@ static void i2s_esp32_tx_callback(void *arg, int status)
425410
goto tx_disable;
426411
}
427412

428-
k_mem_slab_free(stream->data->i2s_cfg.mem_slab, mem_block_tmp);
429-
430413
return;
431414

432415
tx_disable:
@@ -502,11 +485,8 @@ static void i2s_esp32_tx_stop_transfer(const struct device *dev)
502485
i2s_hal_clear_intr_status(hal, I2S_INTR_MAX);
503486
#endif /* SOC_GDMA_SUPPORTED */
504487

505-
if (stream->data->mem_block != NULL) {
506-
k_mem_slab_free(stream->data->i2s_cfg.mem_slab, stream->data->mem_block);
507-
stream->data->mem_block = NULL;
508-
stream->data->mem_block_len = 0;
509-
}
488+
stream->data->mem_block = NULL;
489+
stream->data->mem_block_len = 0;
510490
}
511491

512492
#endif /* I2S_ESP32_IS_DIR_EN(tx) */
@@ -663,7 +643,6 @@ static int i2s_esp32_start_dma(const struct device *dev, enum i2s_dir dir)
663643
LOG_ERR("Failed to start DMA channel: %"PRIu32, stream->conf->dma_channel);
664644
goto unlock;
665645
}
666-
stream->data->dma_pending = true;
667646
#else
668647
#if I2S_ESP32_IS_DIR_EN(rx)
669648
if (dir == I2S_DIR_RX) {
@@ -682,6 +661,8 @@ static int i2s_esp32_start_dma(const struct device *dev, enum i2s_dir dir)
682661
#endif /* I2S_ESP32_IS_DIR_EN(tx) */
683662
#endif /* SOC_GDMA_SUPPORTED */
684663

664+
stream->data->dma_pending = true;
665+
685666
unlock:
686667
irq_unlock(key);
687668
return err;
@@ -1227,7 +1208,6 @@ static int i2s_esp32_trigger_stream(const struct device *dev, const struct i2s_e
12271208
irq_unlock(key);
12281209
return -EIO;
12291210
}
1230-
stream->data->last_block = false;
12311211
stream->data->state = I2S_STATE_RUNNING;
12321212
irq_unlock(key);
12331213
break;
@@ -1245,7 +1225,6 @@ static int i2s_esp32_trigger_stream(const struct device *dev, const struct i2s_e
12451225
stream->data->state = I2S_STATE_STOPPING;
12461226
} else {
12471227
stream->conf->stop_transfer(dev);
1248-
stream->data->last_block = true;
12491228
stream->data->state = I2S_STATE_READY;
12501229
}
12511230

@@ -1280,7 +1259,6 @@ static int i2s_esp32_trigger_stream(const struct device *dev, const struct i2s_e
12801259
stream->data->state = I2S_STATE_STOPPING;
12811260
} else {
12821261
stream->conf->stop_transfer(dev);
1283-
stream->data->last_block = true;
12841262
stream->data->state = I2S_STATE_READY;
12851263
}
12861264
}
@@ -1494,7 +1472,6 @@ static DEVICE_API(i2s, i2s_esp32_driver_api) = {
14941472
.i2s_cfg = {0}, \
14951473
.mem_block = NULL, \
14961474
.mem_block_len = 0, \
1497-
.last_block = false, \
14981475
.stop_without_draining = false, \
14991476
.queue = {}, \
15001477
.irq_handle = NULL, \

0 commit comments

Comments
 (0)