i2S is gave after 1 to 6 index transmission get error code 11 why this happen ??

/*
 * Copyright 2023 NXP
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/i2s.h>
#include <zephyr/drivers/gpio.h>
#include <stdio.h>
#include "codec_header.h"



#define SAMPLE_NO   64
#define CHANNELS    2
#define NUM_BLOCKS  4


/* BLOCK_SIZE in bytes */
#define BLOCK_SIZE (CHANNELS * SAMPLE_NO * sizeof(int16_t))

const struct device *dev_i2s = DEVICE_DT_GET(DT_NODELABEL(i2s20));

/* Stereo interleaved buffers */
static int16_t tx_block[NUM_BLOCKS][CHANNELS * SAMPLE_NO];



/* Sine wave table */
static const int16_t sine[SAMPLE_NO] = {
     3211,  6392,  9511, 12539, 15446, 18204, 20787, 23169,
    25329, 27244, 28897, 30272, 31356, 32137, 32609, 32767,
    32609, 32137, 31356, 30272, 28897, 27244, 25329, 23169,
    20787, 18204, 15446, 12539,  9511,  6392,  3211,     0,
    -3212, -6393, -9512,-12540,-15447,-18205,-20788,-23170,
   -25330,-27245,-28898,-30273,-31357,-32138,-32610,-32767,
   -32610,-32138,-31357,-30273,-28898,-27245,-25330,-23170,
   -20788,-18205,-15447,-12540, -9512, -6393, -3212,    -1
};





static void fill_buf(int16_t *buf, int shift)
{
    for (int i = 0; i < SAMPLE_NO; i++) {
        buf[2 * i]     = sine[i] >> shift;                 /* Left */
        buf[2 * i + 1] = sine[(i + SAMPLE_NO / 4) % SAMPLE_NO] >> shift; /* Right */
    }
}

int main(void)
{
    struct i2s_config i2s_cfg;
    int ret;

    printk("=== System start ===\n");

   // POWER-UP DELAY
    k_msleep(300);
    // provide mclk clock
    //mclk_timer();

    // INIT I2C
    ret = i2c_init_codec();
    if (ret)
    {
        printk("Codec I2C init failed (%d). STOP.\n", ret);
        while (1)
        {
            k_sleep(K_FOREVER);
        }
    }
    printk("Codec I2C init OK\n");

    // CHECK I2S DEVICE
    if (!device_is_ready(dev_i2s)) {
        printk("I2S device not ready\n");
        return -ENODEV;
    }

    // CONFIGURE I2S
    memset(&i2s_cfg, 0, sizeof(i2s_cfg));

    i2s_cfg.word_size = 16;
    i2s_cfg.channels = CHANNELS;
    i2s_cfg.format = I2S_FMT_DATA_FORMAT_I2S;
    i2s_cfg.frame_clk_freq = 8000;
    i2s_cfg.block_size = BLOCK_SIZE;
    i2s_cfg.timeout =1000;
    i2s_cfg.options = I2S_OPT_FRAME_CLK_MASTER | I2S_OPT_BIT_CLK_MASTER;

    ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg);
    if (ret)
    {
        printk("I2S configure failed (%d)\n", ret);
        return ret;
    }

    printk("I2S configured.........\n");

    // PREPARE AUDIO BUFFERS
    for (int i = 0; i < NUM_BLOCKS; i++)
    {
        fill_buf(tx_block[i], i % 3);
    }

    // QUEUE BUFFERS BEFORE START
    ret = i2s_write(dev_i2s, tx_block[0], BLOCK_SIZE);

    ret |= i2s_write(dev_i2s, tx_block[1], BLOCK_SIZE);

    if (ret)
    {
        printk("I2S write failed (%d)\n", ret);
        return ret;
    }

    printk("Initial TX buffers queued\n");

    // NOW START I2S -lrck
    ret = i2s_trigger(dev_i2s, I2S_DIR_TX, I2S_TRIGGER_START);
    if (ret)
    {
        printk("I2S start failed (%d)\n", ret);
        return ret;
    }

    printk("I2S started successfully\n");

 // remaining buffer
    int idx = 2;
    while (1)
    {
        ret = i2s_write(dev_i2s, tx_block[idx % NUM_BLOCKS], BLOCK_SIZE);
       // ret = i2s_write(dev_i2s, tx_block[idx % NUM_BLOCKS], BLOCK_SIZE);
        if (ret == 0)
        {
            idx++;
            k_msleep(1);
        }
        else if (ret == -EAGAIN)
        {
            i2s_trigger(dev_i2s, I2S_DIR_TX, I2S_TRIGGER_DRAIN);
            i2s_trigger(dev_i2s, I2S_DIR_TX, I2S_TRIGGER_START);
            k_msleep(2);
        }
        else
        {
            printk("I2S write error (%d)\n", ret);
            break;
        }
    }
   printk("i2s_write.............");
    return 0;
}


 ovelay file 

&pinctrl {
    i2c21_default: i2c22_default {
        group1 {
            psels =
                    <NRF_PSEL(TWIM_SCL, 1, 12)>,
                    <NRF_PSEL(TWIM_SDA, 1, 13)>;
                    bias-pull-up;
                   
        };
    };

    i2c21_sleep: i2c22_sleep {
        group1 {
            psels = <NRF_PSEL(TWIM_SCL, 1,12)>,
                    <NRF_PSEL(TWIM_SDA, 1, 13)>;
                    low-power-enable;
        };
    };

    i2s20_default: i2s20_default {
        group1 {
            psels = <NRF_PSEL(I2S_SDIN, 1, 6)>, <NRF_PSEL(I2S_SCK_S, 1, 3)>;
        };
    };

    i2s20_sleep: i2s20_sleep {
        group1 {
            psels = <NRF_PSEL(I2S_SDIN, 1, 6)>,
                    <NRF_PSEL(I2S_SDOUT, 1, 5)>,
                    <NRF_PSEL(I2S_SCK_S, 1, 3)>,
                    <NRF_PSEL(I2S_MCK, 1, 4)>,
                    <NRF_PSEL(I2S_LRCK_M, 1, 14)>;
        };
    };


};

&i2c21 {
    status = "disabled";
    pinctrl-0 = <&i2c22_default>;
    pinctrl-1 = <&i2c22_sleep>;
    pinctrl-names = "default", "sleep";

    audiocodec: audiocodec@18 {
        compatible = "i2c-device";
        status = "okay";
        reg = < 0x18 >;
    };
};

&i2s20 {
    status = "okay";
    pinctrl-0 = <&i2s20_default>;
    pinctrl-1 = <&i2s20_sleep>;
    pinctrl-names = "default", "sleep";
};



/ {
     custom_pins{
        compatible = "gpio-keys";

        codec_reset: codec-reset-node {
            gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
            label = "Codec Reset Pin";
        };
    };
};



&i2c21 {
    status = "okay";
};

/ {
    button0: button_0 {
        compatible = "gpio-keys";
        button0_key: button0_key {
            gpios = <&gpio1 15 0>;
            label = "MCUBoot Button";
        };
    };
    leds {
        compatible = "gpio-leds";

        led0: led_0 {
            gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
            label = "User LED 0";
        };
    };
   
       

};

&uart20 {
    status = "okay";
};

&uart20_default {
    group1 {
        psels = <NRF_PSEL(UART_TX, 1, 8)>, <NRF_PSEL(UART_RX, 1, 7)>;
    };
};


/delete-node/ &{/pin-controller/i2c22_default/group2/};

&i2c22 {
    status = "disabled";
};

/delete-node/ &button0;
/delete-node/ &{/pin-controller/i2s20_default/group5/};
/delete-node/ &{/pin-controller/i2s20_default/group2/};
/delete-node/ &{/pin-controller/i2s20_default/group4/};
/delete-node/ &{/pin-controller/i2s20_default/group3/};
 should i implement mclk clock seprate in code ??  
OK
[00:06:49.411,024] <inf> i2s_nrfx: I2S MCK frequency: 256000, actual PCM rate: 8000
Parents
  • Hi,

    Thanks for the updates. I think we may be mixing a few different topics, so just to make sure I understand you correctly and can help in the right direction, could we first align on one thing? Could you please confirm what you want the nRF54L15 to do for the I2S clocks:

    1. Option A:
      The nRF54L15 should generate the I2S clocks (BCLK, LRCK, and MCK), and the codec should use those clocks.
    2. Option B:
      The nRF54L15 should work as an I2S slave, and the clocks (BCLK/LRCK/MCK) are provided by an external source or the codec.

    These two setups are configured very differently, so confirming this first will help avoid confusion. Once this is clear, we can then look at: the I2S -11 (-EAGAIN) messages, and the I2C -5 (I/O error) issue separately if it still happens.

    Thanks for confirming, and we’ll take it step by step from there. Regards,
    Syed Maysum

    1. Option B:
      The nRF54L15 should work as an I2S slave, and the clocks (BCLK/LRCK/MCK) are provided by an external source or the codec.  this one
  • external clcok is use, 4mhz generated here , after thata i2c write is prorper niw and but i2s is failed 

  • /*
     * Codec-style I2S SLAVE playback (continuous)
     * Stable design for nRF54L15 + external codec
     *
     * SPDX-License-Identifier: Apache-2.0
     */

    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/drivers/i2s.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/sys/iterable_sections.h>
    #include "codec/codec.h"

    /* ================= CONFIG ================= */

    #define I2S_NODE DT_NODELABEL(i2s20)

    /* Audio format */
    #define SAMPLE_RATE_HZ     8000
    #define SAMPLE_BIT_WIDTH   16
    #define CHANNELS           2

    /* 100 ms audio block */
    #define SAMPLES_PER_BLOCK  (SAMPLE_RATE_HZ / 10)   /* 800 frames */
    #define BYTES_PER_SAMPLE   sizeof(int16_t)
    #define BLOCK_SIZE         (SAMPLES_PER_BLOCK * CHANNELS * BYTES_PER_SAMPLE)

    /* Buffering */
    #define INIT_BLOCKS        6
    #define BLOCK_COUNT        (INIT_BLOCKS + 6)
    #define TIMEOUT_MS         2000

    /* ================= DEVICE ================= */

    static const struct device *i2s_dev = DEVICE_DT_GET(I2S_NODE);

    /* ================= SINE LUT ================= */
    /* Small lookup table – expanded into big buffers */

    static const int16_t sine_lut[] = {
         3211,  6392,  9511, 12539, 15446, 18204, 20787, 23169,
        25329, 27244, 28897, 30272, 31356, 32137, 32609, 32767,
        -3212, -6393, -9512,-12540,-15447,-18205,-20788,-23170,
       -25330,-27245,-28898,-30273,-31357,-32138,-32610,-32767
    };

    /* ================= MEM SLAB ================= */

    K_MEM_SLAB_DEFINE_IN_SECT_STATIC(
        tx_mem_slab,
        __nocache,
        BLOCK_SIZE,
        BLOCK_COUNT,
        4
    );

    /* ================= HELPERS ================= */

    static void fill_audio_block(int16_t *buf)
    {
        int lut_len = ARRAY_SIZE(sine_lut);

        for (int i = 0; i < SAMPLES_PER_BLOCK; i++) {
            int16_t s = sine_lut[i % lut_len];
            buf[2 * i]     = s;   /* Left */
            buf[2 * i + 1] = s;   /* Right */
        }
    }

    /* ================= MAIN ================= */

    int main(void)
    {
        struct i2s_config cfg;
        void *block;
        int ret;
        int queued = 0;

        printk("Codec-style I2S SLAVE (continuous)\n");

        /* Start external clocks + codec */
        ret = pwm_4mhz();
        if (ret < 0) {
            printk("MCLK start failed\n");
            return ret;
        }

        ret = i2c_init_codec();
        if (ret < 0) {
            printk("Codec init failed\n");
            return ret;
        }

        if (!device_is_ready(i2s_dev)) {
            printk("I2S device not ready\n");
            return -ENODEV;
        }

        /* -------- I2S CONFIG (SLAVE) -------- */
        cfg.word_size      = SAMPLE_BIT_WIDTH;
        cfg.channels       = CHANNELS;
        cfg.format         = I2S_FMT_DATA_FORMAT_I2S;
        cfg.options        = I2S_OPT_FRAME_CLK_SLAVE |
                             I2S_OPT_BIT_CLK_SLAVE;
        cfg.frame_clk_freq = SAMPLE_RATE_HZ;
        cfg.block_size     = BLOCK_SIZE;
        cfg.mem_slab       = &tx_mem_slab;
        cfg.timeout        = TIMEOUT_MS;

        ret = i2s_configure(i2s_dev, I2S_DIR_TX, &cfg);
        if (ret < 0)
        {
            printk("I2S configure failed: %d\n", ret);
            return ret;
        }

        /* -------- Prefill buffers BEFORE START -------- */
        for (int i = 0; i < INIT_BLOCKS; i++)
        {
            ret = k_mem_slab_alloc(&tx_mem_slab, &block, K_FOREVER);
            if (ret < 0)
            {
                printk("Slab alloc failed\n");
                return ret;
            }

            fill_audio_block((int16_t *)block);

            ret = i2s_write(i2s_dev, block, BLOCK_SIZE);
            printk("fill_audio_block %d buffers\n", (int16_t *)block);
            if (ret == -EAGAIN) {
            printk("TX queue full after %d buffers\n", queued);
            k_mem_slab_free(&tx_mem_slab, block);
            break;
        }
        if (ret < 0) {
            printk("i2s_write failed: %d\n", ret);
            return ret;
        }

        queued++;
        }

        /* -------- START ONCE -------- */
        ret = i2s_trigger(i2s_dev, I2S_DIR_TX, I2S_TRIGGER_START);
        if (ret < 0)
        {
            printk("I2S START failed: %d\n", ret);
            return ret;
        }

        printk("Playback running...\n");

        /* -------- Continuous refill (safe) -------- */
        // while (1) {
        //     void *released;

        //     if (i2s_buf_read(i2s_dev, &released, NULL) == 0 && released)
        //     {
        //         fill_audio_block((int16_t *)released);
        //         i2s_write(i2s_dev, released, BLOCK_SIZE);
               
         
        //     }
        // }
       while (1) {
        void *released;
        size_t size;

        int r = i2s_buf_read(i2s_dev, &released, &size);

        if (r == 0 && released) {
            printk("TX buffer completed\n");

            fill_audio_block((int16_t *)released);
            i2s_write(i2s_dev, released, BLOCK_SIZE);
        } else if (r == -EAGAIN) {
            /* No completed buffer yet – this is normal */
            k_msleep(1);
        } else {
            printk("i2s_buf_read error: %d\n", r);
            break;
        }
    }

       
    }
Reply Children
Related