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 Reply Children
  • /*
     * Copyright 2023 NXP
     *
     * SPDX-License-Identifier: Apache-2.0
     */

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

    #define SAMPLE_NO 64
    const struct device *dev_i2s = DEVICE_DT_GET_OR_NULL(DT_NODELABEL(i2s20));

    /* The data represent a sine wave */
    static int16_t data[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,
    };

    /* Fill buffer with sine wave on left channel, and sine wave shifted by
     * 90 degrees on right channel. "att" represents a power of two to attenuate
     * the samples by
     */
    static void fill_buf(int16_t *tx_block, int att)
    {
        int r_idx;

        for (int i = 0; i < SAMPLE_NO; i++)
        {
            /* Left channel is sine wave */
            tx_block[2 * i] = data[i] / (1 << att);
            /* Right channel is same sine wave, shifted by 90 degrees */
            r_idx = (i + (ARRAY_SIZE(data) / 4)) % ARRAY_SIZE(data);
            tx_block[2 * i + 1] = data[r_idx] / (1 << att);
        }
    }

    #define NUM_BLOCKS 20
    /* BLOCK_SIZE in bytes: 2 channels * SAMPLE_NO samples * 2 bytes per sample */
    #define BLOCK_SIZE (2 * SAMPLE_NO * sizeof(int16_t))

    #ifdef CONFIG_NOCACHE_MEMORY
        #define MEM_SLAB_CACHE_ATTR __nocache
    #else
        #define MEM_SLAB_CACHE_ATTR
    #endif /* CONFIG_NOCACHE_MEMORY */

    /* backing buffer for mem_slab */
    static char MEM_SLAB_CACHE_ATTR __aligned(WB_UP(32))
        _k_mem_slab_buf_tx_0_mem_slab[(NUM_BLOCKS) * WB_UP(BLOCK_SIZE)];

    static STRUCT_SECTION_ITERABLE(k_mem_slab, tx_0_mem_slab) =
        Z_MEM_SLAB_INITIALIZER(tx_0_mem_slab, _k_mem_slab_buf_tx_0_mem_slab,
                    WB_UP(BLOCK_SIZE), NUM_BLOCKS);

    /* Release one played block returned by the I2S driver (buffer API) */
    static void release_played_block(const struct device *dev)
    {
        void *block;

        while (i2s_buf_read(dev, &block, NULL) == 0 && block)
        {
            k_mem_slab_free(&tx_0_mem_slab, &block);
        }
    }


    int main(void)
    {
        void *tx_block[NUM_BLOCKS];
        struct i2s_config i2s_cfg;
        int ret;
        int tx_idx;

        printf("Enter to main........\n");

        k_msleep(300);

        ret=pwm_4mhz(); // pwm 4mhz generation for i2s mclk

        if (ret < 0)
        {
            printf("PWM 4mhz generation is failed .\n");
        }

        if (!dev_i2s)
        {
            printf("I2S device node 'i2s20' not found. Check DT label.\n");
            return -ENODEV;
        }

        if (!device_is_ready(dev_i2s))
        {
            printf("I2S device not ready...\n");
            return -ENODEV;
        }
        ret = i2c_init_codec(); // init i2c codec
        // gpio_pin_configure_dt();

        if (ret < 0)
        {
            printf("I2c init is failed .\n");
        }

        /* Configure I2S stream */
        i2s_cfg.word_size = 16U;
        i2s_cfg.channels = 2U;
        i2s_cfg.format = I2S_FMT_DATA_FORMAT_I2S;
        i2s_cfg.frame_clk_freq = 8000; /* set to your desired sample rate */
        i2s_cfg.block_size = BLOCK_SIZE;
        i2s_cfg.timeout = 1000; /* ms */
        /* Configure the Transmit port as slave */
        i2s_cfg.options = I2S_OPT_FRAME_CLK_SLAVE | I2S_OPT_BIT_CLK_SLAVE;
        i2s_cfg.mem_slab = &tx_0_mem_slab;


        ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg);
        if (ret < 0)
        {
            printf("Failed to configure I2S stream: %d\n", ret);
            return ret;
        }

        printf("I2S configured successfully.\n");

        printf("Preparing TX blocks..\n");

      /* Allocate + fill buffers */
        for (int i = 0; i < NUM_BLOCKS; i++) {
            k_mem_slab_alloc(&tx_0_mem_slab, &tx_block[i], K_FOREVER);
            fill_buf(tx_block[i], i % 3);
        }

        /* ---- CRITICAL FIX: queue ≥4 buffers BEFORE START ---- */
        for (int i = 0; i < 4; i++)
        {
            ret = i2s_write(dev_i2s, tx_block[i], BLOCK_SIZE);
            if (ret) return ret;
        }

        ret = i2s_trigger(dev_i2s, I2S_DIR_TX, I2S_TRIGGER_START);
        if (ret) return ret;

        /* Feed remaining buffers */
        for (int i = 4; i < NUM_BLOCKS; i++) {

            release_played_block(dev_i2s);

            ret = i2s_write(dev_i2s, tx_block[i], BLOCK_SIZE);
            if (ret == -EAGAIN) {
                i--;
                continue;
            }
            if (ret < 0) {
                /* proper recovery */
                i2s_trigger(dev_i2s, I2S_DIR_TX, I2S_TRIGGER_STOP);
                i2s_trigger(dev_i2s, I2S_DIR_TX, I2S_TRIGGER_DROP);
                break;
            }
           
        }

    }  hi , I have one problem here i got -5 error when i write i2s after 7th write why ??
  • 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;
        }
    }

       
    }
Related