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,

    Error code 11 is -EAGAIN, which simply means the I2S TX queue was full and i2s_write() timed out waiting for a free slot. This is expected if audio buffers are queued faster than the I2S hardware can transmit them. When this happens, one of the way could be to wait for some micro seconds and retry i2s_write().

    Also note that as previously recommended increasing NUM_BLOCKS only adds more application buffers; it doesn’t change the driver’s internal TX queue size. To check that part, could you please share the relevant section of your prj.conf, especially any I2S or nrfx-related options?

    Regarding MCK, you don’t need to generate it separately in code when I2S is set up as master.

    Best Regards,
    Syed Maysum

  • CONFIG_PRINTK=y
    CONFIG_SERIAL=y
    CONFIG_LOG=y
    CONFIG_LOG_DEFAULT_LEVEL=3
    CONFIG_GPIO=y
    CONFIG_I2C=y
    CONFIG_I2S=y

    CONFIG_I2C_NRFX=y
    CONFIG_I2S_NRFX_TX_BLOCK_COUNT=8




    prj.cfg

  • /**
     * Register declaration
     */

    const register_value REGISTER_DATA[] = {
        //          # reg[0][0]   = 0x00   ; Select Page 0
        {0, 0x00},
        //          # reg[0][1]   = 0x01   ; S/W Reset
        {1, 0x01},
        //          # reg[0][4]   = 0x03   ; PLL_CLKIN = MCLK = 4 MHz., CODEC_CLKIN = PLL_CLCK
        {4, 0x03},
        //          # reg[0][5]   = 0xD4   ; PLL Power up, P = 5, R = 4
        {5, 0xD4},
        //          # reg[0][6]   = 0x20   ; J = 32
        {6, 0x20},
        //          # reg[0][7]   = 0x00   ; D = 0000, D(13:8) = 0
        {7, 0x00},
        //          # reg[0][8]   = 0x00   ; D(7:0) = 0
        {8, 0x00},
        //          # reg[0][27]  = 0x0C   ; Mode = I2S, wordlength = 16, output mode
        {27, 0x0C},
        //          # reg[0][11]  = 0x84   ; DAC Powerup NDAC = 4 (DAC_MAC_CLK = 102.4 MHz/4 = 25.6 MHz.)
        {11, 0x84},
        //          # reg[0][12]  = 0x99   ; DAC Powerup MDAC = 25  (DAC_MOD_CLK = 25.6/ 25 = 1.024 MHz.)
        {12, 0x99},
        //          # reg[0][14]  = 0x80   ;  DOSR = 128 (ADC Fs = 1.024 / 128 = 8.0 KHz.)
        {14, 0x80},
        //          # reg[0][18]  = 0x84   ; ADC Powerup NADC = 4 (ADC_MAC_CLK = 102.4 MHz/4 = 25.6 MHz.)
        {18, 0x84},
        //          # reg[0][19]  = 0x99   ; ADC Powerup MADC = 25 (ADC_MOD_CLK = 25.6 MHz/25 = 1.024 MHz.)
        {19, 0x99},
        //          # reg[0][20]  = 0x80   ; AOSR = 20 (ADC Fs = 1.024 / 128 = 8.0 KHz.)
        {20, 0x80},
        //          # reg[0][29]  = 0X01   ; DAC_MOD_CLOCK
        {29, 0x01},
        //          # reg[0][30]  = 0x84   ; BCLK N-divider, BCLK divider N = 4
        {30, 0x84},
        //          # reg[0][0]   = 0x01   ; Select Page 1
        {0, 0x01},
        //          # reg[1][46]  = 0x0B   ; MICBIAS always on, MICBIAS = 2.5V
        {46, 0x0A},
        //          # reg[1][48]  = 0x40   ; MICLP is selected for left of Mic PGA P @ 10k input impedance
        {48, 0x40},
        //          # reg[1][49]  = 0x40   ; CM is selected for right of Mic PGA M @ 10k input impedance
        {49, 0x40},
        //          # reg[1][47]  = 0x0    ; MIC PGA ;  db
        {47, 0x00},
        //          # reg[0][0]   = 0x00   ; Select Page 0
        {0, 0x00},
        //          # reg[0][81]  = 0x80   ; Powerup ADC channel (soft step enable)
        {81, 0x80},
        //          # reg[0][83]  = 0x00   ; ADC volume = 0dB
        {83, 0x00},
        //           reg[0][82]  = 0x00   ; Unmute ADC channel
        {82, 0x00},

    };
  • Thanks for sharing the details and prj.conf. With retry pacing in place and CONFIG_I2S_NRFX_TX_BLOCK_COUNT=8, the earlier -EAGAIN TX queue behavior should now be handled correctly on the application side.  

    i got same -eagen error 

  • Hi,

    On nRF54L15, the master clock (MCK) is generated by a frequency generator based on the MCKFREQ register and the sample rate (LRCK) is then derived as LRCK = MCK / RATIO. 

    Your log shows the I2S driver is currently selecting MCK=256 kHz with LRCK=8 kHz, which implies a 32x ratio. That is why the codec (which expects ~4 MHz MCK) does not match. If the codec requires ~4 MHz MCK, the I2S clocks should be configured for RATIO=512x so that at 8 kHz sample rate you get MCK = 8 kHz Ă— 512 = 4.096 MHz.

    So if you want to get a higher MCK (~4 MHz), you should switch to using the nrfx_i2s driver directly. In nrfx_i2s, you can explicitly set:

    1. RATIO: Set NRF_I2S_RATIO_512X in the configuration structure, Note that at a 512x ratio, 4.096 MHz MCK provides an exact 8 kHz sample rate (4,096,000 / 512 = 8,000)
    2. MCKFREQ: Use the frequency equation to target 4.096 MHz. For a 32 MHz source, a MCKFREQ value of 0x20C49000 targets 4.096 MHz (12 LSB must be 0 on nRF54L15).

    Hopefully it should work. Best Regards,
    Syed Maysum

  • #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/i2s.h>
    #include <zephyr/sys/printk.h>
    #include <string.h>
    #include "codec_header.h"

    /* CONFIG */
    #define SAMPLE_NO     64
    #define CHANNELS      2
    #define NUM_BLOCKS    4

    #define SAMPLE_RATE   8000
    #define WORD_SIZE     16

    #define BLOCK_SIZE (SAMPLE_NO * CHANNELS * sizeof(int16_t))

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

    // STATIC DMA-SAFE BUFFERS
    static int16_t tx_buf[NUM_BLOCKS][SAMPLE_NO * CHANNELS];

    /* SINE WAVE */
    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
    };

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

    int main(void)
    {
        struct i2s_config i2s_cfg = {0};
        int ret;
        int idx = 0;

        printk("=== I2S static buffer test ===\n");

        if (!device_is_ready(dev_i2s)) {
            printk("I2S device not ready\n");
            return 0;
        }

        /* Codec init */
        ret = i2c_init_codec();

       // k_msleep(1000);

        if (ret) {
            printk("Codec init failed (%d)\n", ret);
            return 0;
        }

        // I2S CONFIG
        i2s_cfg.word_size      = WORD_SIZE;
        i2s_cfg.channels       = CHANNELS;
        i2s_cfg.format         = I2S_FMT_DATA_FORMAT_I2S;
        i2s_cfg.frame_clk_freq = SAMPLE_RATE;
        i2s_cfg.block_size     = BLOCK_SIZE;
        i2s_cfg.timeout        = 2000;
        i2s_cfg.options =
            I2S_OPT_FRAME_CLK_SLAVE |
            I2S_OPT_BIT_CLK_SLAVE;

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

        // Queue initial buffers
        for (int i = 0; i < NUM_BLOCKS; i++)
        {
            fill_buf(tx_buf[i], i);

            i2s_write(dev_i2s, tx_buf[i], BLOCK_SIZE);
        }

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

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

        while (1)
        {
            fill_buf(tx_buf[idx % NUM_BLOCKS], idx % 3);

            ret = i2s_write( dev_i2s, tx_buf[idx % NUM_BLOCKS],BLOCK_SIZE);

            if (ret == 0)
            {
                idx++;
            } else if (ret == -EAGAIN) {
                k_msleep(1);
            } else {
                printk("I2S write error (%d)\n", ret);
                break;
            }
        }

        i2s_trigger(dev_i2s, I2S_DIR_TX, I2S_TRIGGER_DROP);

        printf("I2S test done\n");
       
        return 0;
    }  this is my code but here i am not using any k/-mem_slab for aloocation only static alloaction is done so its have any issue.
  • One of another issue related to i2c communicatrion- 

    Initially the I2C communication works correctly, but after next debugg it starts failing with error -5 (I/O error) again another debugg it would be work correct again it will fail - I am confused with thi bug

Reply Children
Related