@@ -403,9 +403,13 @@ static void i2s_esp32_tx_callback(void *arg, int status)
403
403
404
404
err = k_msgq_get (& stream -> data -> queue , & item , K_NO_WAIT );
405
405
if (err < 0 ) {
406
- stream -> data -> state = I2S_STATE_ERROR ;
407
- LOG_ERR ("TX queue empty: %d" , err );
408
- goto tx_disable ;
406
+ /*
407
+ * Stop DMA and transition to READY, so the next write()
408
+ * can auto-kick TX without requiring a new START trigger.
409
+ */
410
+ stream -> data -> state = I2S_STATE_READY ;
411
+ stream -> conf -> stop_transfer (dev );
412
+ return ;
409
413
}
410
414
411
415
mem_block_tmp = stream -> data -> mem_block ;
@@ -459,7 +463,13 @@ static int i2s_esp32_tx_start_transfer(const struct device *dev)
459
463
460
464
err = k_msgq_get (& stream -> data -> queue , & item , K_NO_WAIT );
461
465
if (err < 0 ) {
462
- return - ENOMEM ;
466
+ /*
467
+ * No data queued yet. Leave mem_block NULL and return success.
468
+ * START will keep TX in READY; next write() will auto-kick TX.
469
+ */
470
+ stream -> data -> mem_block = NULL ;
471
+ stream -> data -> mem_block_len = 0 ;
472
+ return 0 ;
463
473
}
464
474
465
475
stream -> data -> mem_block = item .buffer ;
@@ -1193,6 +1203,11 @@ static int i2s_esp32_trigger_stream(const struct device *dev, const struct i2s_e
1193
1203
1194
1204
switch (cmd ) {
1195
1205
case I2S_TRIGGER_START :
1206
+ /* if already streaming, treat as success */
1207
+ if (stream -> data -> state == I2S_STATE_RUNNING ) {
1208
+ LOG_DBG ("START ignored: already RUNNING" );
1209
+ return 0 ;
1210
+ }
1196
1211
if (stream -> data -> state != I2S_STATE_READY ) {
1197
1212
LOG_ERR ("START - Invalid state: %d" , (int )stream -> data -> state );
1198
1213
return - EIO ;
@@ -1223,12 +1238,27 @@ static int i2s_esp32_trigger_stream(const struct device *dev, const struct i2s_e
1223
1238
return - EIO ;
1224
1239
}
1225
1240
stream -> data -> last_block = false;
1241
+ /*
1242
+ * If no mem_block was available (queue empty), stay READY.
1243
+ * The next write() will auto-kick TX into RUNNING.
1244
+ */
1245
+ if (dir == I2S_DIR_TX && stream -> data -> mem_block == NULL &&
1246
+ !stream -> data -> dma_pending ) {
1247
+ stream -> data -> state = I2S_STATE_READY ;
1248
+ irq_unlock (key );
1249
+ return 0 ;
1250
+ }
1226
1251
stream -> data -> state = I2S_STATE_RUNNING ;
1227
1252
irq_unlock (key );
1228
1253
break ;
1229
1254
1230
1255
case I2S_TRIGGER_STOP :
1231
1256
key = irq_lock ();
1257
+ if (stream -> data -> state == I2S_STATE_READY ) {
1258
+ /* Already idle; treat STOP as success */
1259
+ irq_unlock (key );
1260
+ return 0 ;
1261
+ }
1232
1262
if (stream -> data -> state != I2S_STATE_RUNNING ) {
1233
1263
irq_unlock (key );
1234
1264
LOG_ERR ("STOP - Invalid state: %d" , (int )stream -> data -> state );
@@ -1249,9 +1279,49 @@ static int i2s_esp32_trigger_stream(const struct device *dev, const struct i2s_e
1249
1279
1250
1280
case I2S_TRIGGER_DRAIN :
1251
1281
key = irq_lock ();
1252
- if (stream -> data -> state != I2S_STATE_RUNNING ) {
1282
+ int32_t st = stream -> data -> state ;
1283
+
1284
+ if (st == I2S_STATE_READY ) {
1285
+ #if I2S_ESP32_IS_DIR_EN (tx )
1286
+ if (dir == I2S_DIR_TX ) {
1287
+ bool have_data = (k_msgq_num_used_get (& stream -> data -> queue ) > 0 );
1288
+
1289
+ /* If there's data queued and TX is idle, kick once and drain */
1290
+ if (have_data && !stream -> data -> dma_pending ) {
1291
+ int kick = stream -> conf -> start_transfer (dev );
1292
+
1293
+ if (kick < 0 ) {
1294
+ irq_unlock (key );
1295
+ LOG_ERR ("DRAIN - autostart failed: %d" , kick );
1296
+ return - EIO ;
1297
+ }
1298
+ stream -> data -> last_block = false;
1299
+ stream -> data -> stop_without_draining = false;
1300
+ stream -> data -> state = I2S_STATE_STOPPING ;
1301
+ irq_unlock (key );
1302
+ break ;
1303
+ }
1304
+
1305
+ /* Nothing to drain (idle and no queued blocks) */
1306
+ if (!have_data && !stream -> data -> dma_pending ) {
1307
+ irq_unlock (key );
1308
+ return 0 ;
1309
+ }
1310
+ }
1311
+ #endif /* I2S_ESP32_IS_DIR_EN(tx) */
1312
+
1313
+ #if I2S_ESP32_IS_DIR_EN (rx )
1314
+ if (dir == I2S_DIR_RX ) {
1315
+ /* If RX is idle and no DMA pending, nothing to drain */
1316
+ if (!stream -> data -> dma_pending ) {
1317
+ irq_unlock (key );
1318
+ return 0 ;
1319
+ }
1320
+ }
1321
+ #endif /* I2S_ESP32_IS_DIR_EN(rx) */
1322
+ } else if (st != I2S_STATE_RUNNING ) {
1253
1323
irq_unlock (key );
1254
- LOG_ERR ("DRAIN - Invalid state: %d" , (int )stream -> data -> state );
1324
+ LOG_ERR ("DRAIN - Invalid state: %d" , (int )st );
1255
1325
return - EIO ;
1256
1326
}
1257
1327
@@ -1460,6 +1530,36 @@ static int i2s_esp32_write(const struct device *dev, void *mem_block, size_t siz
1460
1530
return err ;
1461
1531
}
1462
1532
1533
+ /*
1534
+ * Auto-restart TX after an underrun or a START with no data:
1535
+ * If TX is in READY and no DMA is pending and there's no current block,
1536
+ * kick DMA immediately so we don't require a new START trigger.
1537
+ */
1538
+ if (stream -> data -> state == I2S_STATE_READY && !stream -> data -> dma_pending &&
1539
+ stream -> data -> mem_block == NULL ) {
1540
+ unsigned int key = irq_lock ();
1541
+
1542
+ if (stream -> data -> state == I2S_STATE_READY && !stream -> data -> dma_pending &&
1543
+ stream -> data -> mem_block == NULL ) {
1544
+ int kick = stream -> conf -> start_transfer (dev );
1545
+
1546
+ if (kick < 0 ) {
1547
+ irq_unlock (key );
1548
+ LOG_ERR ("TX auto-restart failed: %d" , kick );
1549
+ return kick ;
1550
+ }
1551
+ stream -> data -> last_block = false;
1552
+ /*
1553
+ * If start_transfer pulled from the queue, we are RUNNING;
1554
+ * if not (shouldn't happen here), stay READY.
1555
+ */
1556
+ if (stream -> data -> mem_block != NULL || stream -> data -> dma_pending ) {
1557
+ stream -> data -> state = I2S_STATE_RUNNING ;
1558
+ }
1559
+ }
1560
+ irq_unlock (key );
1561
+ }
1562
+
1463
1563
return 0 ;
1464
1564
#else
1465
1565
LOG_ERR ("I2S_DIR_TX not enabled" );
0 commit comments