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
  • Hi,

    To solve this efficiently, we need to validate one interface at a time. I’ve reviewed your code carefully and there are concrete I2C bugs that must be fixed before we continue with I2S.

    Issue 1: Incorrect I2C transfer lengths (must be fixed)

    In multiple places you request 2 bytes from the I2C driver but store them in 1-byte variables, which is invalid and can corrupt memory or cause the codec to NACK. Examples from your code:

    codec_probe():

    uint8_t read_back = 0;
    i2c_write_read_dt(&dev_i2c, &reg0, 2, &read_back, 2);

    Here read_back is 1 byte, but you request a 2-byte read.

    read_eg():

    uint8_t reg = 0xD4;
    uint8_t val = 0;
    i2c_write_read_dt(&dev_i2c, &reg, 2, &val, 2);

    Here: reg is 1 byte but write_len = 2 and val is 1 byte but read_len = 2

    Both are invalid and must be corrected everywhere in the code.

    Issue 2: Wrong API used for register writes

    You are using i2c_write_read_dt() for normal register writes (write-only operations). So for normal writes please try using i2c_write_dt(). Correct patterns (assuming 8-bit register + 8-bit data):

    Register write:

    uint8_t buf[2] = { reg, val };
    ret = i2c_write_dt(&dev_i2c, buf, 2);

    Register read:

    ret = i2c_write_read_dt(&dev_i2c, &reg, 1, &val, 1);

    So before testing I2S again please disable I2S in the overlay (&i2s20 { status = "disabled"; };) or physically disconnect all I2S lines and first fix all I2C calls so that transfer lengths exactly match buffer sizes and i2c_write_dt() is used for write-only operations. Then read the same codec register 10,000 times in a loop (this test should complete with 0 occurrences of -EIO).

    Once this I2C-only test is stable, we will move on to validating I2S in isolation. Thanks

  • #define DPPI_CH    0
    #define GPIOTE_CH  0
    static const struct gpio_dt_spec pwm_Tim = GPIO_DT_SPEC_GET(PWM_NODE, gpios); // for reset pin
    void start_timer(void)
    {
        // gpio comfigure
        gpio_pin_configure_dt(&pwm_Tim, GPIO_OUTPUT_INACTIVE);
        gpio_pin_set_dt(&pwm_Tim, 0);

        // port selection
        uint32_t port =
            (pwm_Tim.port == DEVICE_DT_GET(DT_NODELABEL(gpio1))) ? 1 : 0;


        // cofigure GPIOTE channel
        NRF_GPIOTE20->CONFIG[GPIOTE_CH] =
            (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
            (pwm_Tim.pin << GPIOTE_CONFIG_PSEL_Pos) |
            (port << GPIOTE_CONFIG_PORT_Pos) |
            (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos) |
            (GPIOTE_CONFIG_OUTINIT_Low << GPIOTE_CONFIG_OUTINIT_Pos);

        // Tiimer22 configuration
        NRF_TIMER22->MODE = TIMER_MODE_MODE_Timer;
        NRF_TIMER22->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
        NRF_TIMER22->PRESCALER = 0;   // 16 MHz
        NRF_TIMER22->TASKS_CLEAR = 1;

        NRF_TIMER22->CC[0] = 2;   // 125 ns toggle this time


        NRF_TIMER22->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk;    // clear on compare1
     

        NRF_TIMER22->PUBLISH_COMPARE[0] =
            (DPPI_CH << TIMER_PUBLISH_COMPARE_CHIDX_Pos) |
            TIMER_PUBLISH_COMPARE_EN_Msk;                              // publish on compare0

        NRF_GPIOTE20->SUBSCRIBE_OUT[GPIOTE_CH] =
            (DPPI_CH << GPIOTE_SUBSCRIBE_OUT_CHIDX_Pos) |
            GPIOTE_SUBSCRIBE_OUT_EN_Msk;                       // subscribe to GPIOTE channel
         /// dppi comfiguation
        NRF_DPPIC20->CHENSET = (1UL << DPPI_CH);
        // timer22 start
        NRF_TIMER22->TASKS_START = 1;
    }  Timer is fluctuation - not pwm (square is produce) - 4mhz is produce but variation is there ..what will i do , amplitude is millivolt 
  • Hi

    I see you’re experimenting with generating a 4 MHz MCLK now. Just to make sure we’re aligned: I don’t yet have confirmation that the original I2C issue is resolved. Before we move further with MCLK/I2S, could you please confirm:

    1. Have the I2C read/write length issues been fixed (no 2-byte transfers into 1-byte variables, and i2c_write_dt() used for write-only operations)?
    2. With I2S disabled or disconnected, does an I2C free-run test (e.g. 10,000 register reads) complete with zero -EIO errors?

    Once that’s confirmed, we can continue with the MCLK/I2S part. Thanks

    Regards,
    Syed Maysum

Related