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
  • what changes i made my code to get proper transmission

    Best Regards

    Sharon

  • Hi,

    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.

    Regarding MCK: the nRF I2S peripheral does support generating MCK at 256x LRCK as shown here in master mode using the appropriate I2S ratio configuration. The current log shows 32x LRCK simply because of the current I2S clock configuration, not due to a hardware limitation.

    The remaining question is whether your codec strictly requires 256x LRCK or just recommends it. If it is required, the next step would be to adjust the I2S configuration (ratio and MCK frequency) to generate MCK for the selected sample rate and verify that this frequency is achievable and within the codec’s tolerance.

    Best Regards,
    Syed Maysum


  • /**
     * 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 

Reply Children
No Data
Related