/* Исправленная функция подготовки трансфера: блоки берем СТРОГО из пула TX */
static bool prepare_transfer(const struct device *i2s_dev_tx)
{
int ret;
for (int i = 0; i < ZEPHYR_AUDIO_INITIAL_BLOCKS; ++i)
{
void *mem_block;
/* ОШИБКА ИСПРАВЛЕНА: используем mem_slab_tx */
ret = k_mem_slab_alloc(&mem_slab_tx, &mem_block, K_NO_WAIT);
if (ret < 0)
{
printk("Failed to allocate TX block from mem_slab_tx: %d\n", ret);
return false;
}
memset(mem_block, 0, ZEPHYR_AUDIO_BLOCK_SIZE);
ret = i2s_write(i2s_dev_tx, mem_block, ZEPHYR_AUDIO_BLOCK_SIZE);
if (ret < 0)
{
printk("Failed to write block %d: %d\n", i, ret);
return false;
}
}
return true;
}
/* Исправленная функция старта: учитываем дуплекс SAI */
int zephyr_i2s_start(uint8_t audio_in)
{
printf("%s(%d) audio_in=%d\n", __FUNCTION__, __LINE__, audio_in);
/* Если один из потоков уже запустил устройство, выходим */
if (start_stream) {
return 0;
}
/* Пре-фил очереди нужен только для воспроизведения (TX) */
if (!prepare_transfer(i2s_dev_tx))
{
return -1;
}
/* Запускаем оба плеча одновременно для синхронизации */
if (!trigger_command(i2s_dev_rx, i2s_dev_tx, I2S_TRIGGER_START))
{
return -1;
}
start_stream = 1;
return 0;
}
/* Исправленная инициализация: настройка кодека и SAI с разными Slab */
int zephyr_i2s_audio_init(void)
{
struct i2s_config config;
#if DT_NODE_HAS_STATUS(DT_NODELABEL(audio_codec), okay)
const struct device *const codec_dev = DEVICE_DT_GET(DT_NODELABEL(audio_codec));
struct audio_codec_cfg audio_cfg;
audio_cfg.dai_route = AUDIO_ROUTE_PLAYBACK_CAPTURE;
audio_cfg.dai_type = AUDIO_DAI_TYPE_I2S;
audio_cfg.dai_cfg.i2s.word_size = SAMPLE_BIT_WIDTH;
audio_cfg.dai_cfg.i2s.channels = NUMBER_OF_CHANNELS;
audio_cfg.dai_cfg.i2s.format = I2S_FMT_DATA_FORMAT_I2S;
audio_cfg.dai_cfg.i2s.options = I2S_OPT_FRAME_CLK_MASTER;
audio_cfg.dai_cfg.i2s.frame_clk_freq = SAMPLE_FREQUENCY;
/* Кодеку указываем любой пул (обычно используется только для валидации) */
audio_cfg.dai_cfg.i2s.mem_slab = &mem_slab_tx;
audio_cfg.dai_cfg.i2s.block_size = ZEPHYR_AUDIO_BLOCK_SIZE;
audio_codec_configure(codec_dev, &audio_cfg);
k_msleep(100);
#else
printk("No audio_codec found in DTS!\n");
return -1;
#endif
if (!device_is_ready(i2s_dev_rx) || !device_is_ready(i2s_dev_tx))
{
printk("I2S devices not ready\n");
return -1;
}
/* Общие параметры SAI */
config.word_size = SAMPLE_BIT_WIDTH;
config.channels = NUMBER_OF_CHANNELS;
config.format = I2S_FMT_DATA_FORMAT_I2S;
config.options = I2S_OPT_BIT_CLK_MASTER | I2S_OPT_FRAME_CLK_MASTER;
config.frame_clk_freq = SAMPLE_FREQUENCY;
config.block_size = ZEPHYR_AUDIO_BLOCK_SIZE;
config.timeout = TIMEOUT;
/* ИСПРАВЛЕНО: Теперь вызываем функцию, которая разделяет mem_slab_rx и mem_slab_tx */
if (!configure_streams(i2s_dev_rx, i2s_dev_tx, &config))
{
return -1;
}
return 0;
}