NRF5340 Audio DK - I2S - Multiple IRQ Invocations

I'm trying to setup a I2S module by referring the I2S module given in the nrf5340-audio application. This is my audio_i2s.c file.

/*
* Copyright (c) 2021, PACKETCRAFT, INC.
*
* SPDX-License-Identifier: LicenseRef-PCFT
*/

#include "audio_i2s.h"

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/pinctrl.h>
#include <nrfx_i2s.h>
#include <nrfx_clock.h>
#include <audio_module/audio_module.h>

#define I2S_NL DT_NODELABEL(i2s0)

#define HFCLKAUDIO_12_288_MHZ 0x9BAE

enum audio_i2s_state {
AUDIO_I2S_STATE_UNINIT,
AUDIO_I2S_STATE_IDLE,
AUDIO_I2S_STATE_STARTED,
};

static enum audio_i2s_state state = AUDIO_I2S_STATE_UNINIT;

PINCTRL_DT_DEFINE(I2S_NL);

#if CONFIG_AUDIO_SAMPLE_RATE_16000_HZ
#define CONFIG_AUDIO_RATIO NRF_I2S_RATIO_384X
#elif CONFIG_AUDIO_SAMPLE_RATE_24000_HZ
#define CONFIG_AUDIO_RATIO NRF_I2S_RATIO_256X
#elif CONFIG_AUDIO_SAMPLE_RATE_48000_HZ
#define CONFIG_AUDIO_RATIO NRF_I2S_RATIO_128X
#else
#error "Current AUDIO_SAMPLE_RATE_HZ setting not supported"
#endif

static nrfx_i2s_t i2s_inst = NRFX_I2S_INSTANCE(0);

static nrfx_i2s_config_t cfg = {
/* Pins are configured by pinctrl. */
.skip_gpio_cfg = true,
.skip_psel_cfg = true,
.irq_priority = DT_IRQ(I2S_NL, priority),
.mode = NRF_I2S_MODE_MASTER,
.format = NRF_I2S_FORMAT_I2S,
.alignment = NRF_I2S_ALIGN_LEFT,
.ratio = CONFIG_AUDIO_RATIO,
.mck_setup = 0x66666000,
#if (CONFIG_AUDIO_BIT_DEPTH_16)
.sample_width = NRF_I2S_SWIDTH_16BIT,
#elif (CONFIG_AUDIO_BIT_DEPTH_32)
.sample_width = NRF_I2S_SWIDTH_32BIT,
#else
#error Invalid bit depth selected
#endif /* (CONFIG_AUDIO_BIT_DEPTH_16) */
.channels = NRF_I2S_CHANNELS_STEREO,
.clksrc = NRF_I2S_CLKSRC_ACLK,
.enable_bypass = false,
};

static i2s_blk_comp_callback_t i2s_blk_comp_callback;

static void i2s_comp_handler(nrfx_i2s_buffers_t const *released_bufs, uint32_t status)
{
uint32_t frame_start_ts = audio_sync_timer_capture_get();

if ((status == NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED) && released_bufs &&
i2s_blk_comp_callback && (released_bufs->p_rx_buffer || released_bufs->p_tx_buffer)) {
i2s_blk_comp_callback(frame_start_ts, released_bufs->p_rx_buffer,
released_bufs->p_tx_buffer);
}
}

void audio_i2s_set_next_buf(const uint8_t *tx_buf, uint32_t *rx_buf)
{
__ASSERT_NO_MSG(state == AUDIO_I2S_STATE_STARTED);
if (IS_ENABLED(CONFIG_STREAM_BIDIRECTIONAL) || (CONFIG_AUDIO_DEV == GATEWAY)) {
__ASSERT_NO_MSG(rx_buf != NULL);
}

if (IS_ENABLED(CONFIG_STREAM_BIDIRECTIONAL) || (CONFIG_AUDIO_DEV == HEADSET)) {
__ASSERT_NO_MSG(tx_buf != NULL);
}

const nrfx_i2s_buffers_t i2s_buf = { .p_rx_buffer = rx_buf,
.p_tx_buffer = (uint32_t *)tx_buf };

nrfx_err_t ret;

ret = nrfx_i2s_next_buffers_set(&i2s_inst, &i2s_buf);
__ASSERT_NO_MSG(ret == NRFX_SUCCESS);
}

void audio_i2s_start(const uint8_t *tx_buf, uint32_t *rx_buf)
{
__ASSERT_NO_MSG(state == AUDIO_I2S_STATE_IDLE);
if (IS_ENABLED(CONFIG_STREAM_BIDIRECTIONAL) || (CONFIG_AUDIO_DEV == GATEWAY)) {
__ASSERT_NO_MSG(rx_buf != NULL);
}

if (IS_ENABLED(CONFIG_STREAM_BIDIRECTIONAL) || (CONFIG_AUDIO_DEV == HEADSET)) {
__ASSERT_NO_MSG(tx_buf != NULL);
}

const nrfx_i2s_buffers_t i2s_buf = { .p_rx_buffer = rx_buf,
.p_tx_buffer = (uint32_t *)tx_buf };

nrfx_err_t ret;

/* Buffer size in 32-bit words */
ret = nrfx_i2s_start(&i2s_inst, &i2s_buf, I2S_SAMPLES_NUM, 0);
__ASSERT_NO_MSG(ret == NRFX_SUCCESS);

state = AUDIO_I2S_STATE_STARTED;
}

void audio_i2s_stop(void)
{
__ASSERT_NO_MSG(state == AUDIO_I2S_STATE_STARTED);

nrfx_i2s_stop(&i2s_inst);

state = AUDIO_I2S_STATE_IDLE;
}

void audio_i2s_blk_comp_cb_register(i2s_blk_comp_callback_t blk_comp_callback)
{
i2s_blk_comp_callback = blk_comp_callback;
}

void audio_i2s_init(void)
{
__ASSERT_NO_MSG(state == AUDIO_I2S_STATE_UNINIT);

nrfx_err_t ret;

nrfx_clock_hfclkaudio_config_set(HFCLKAUDIO_12_288_MHZ);

NRF_CLOCK->TASKS_HFCLKAUDIOSTART = 1;

/* Wait for ACLK to start */
while (!NRF_CLOCK_EVENT_HFCLKAUDIOSTARTED) {
k_sleep(K_MSEC(1));
}

ret = pinctrl_apply_state(PINCTRL_DT_DEV_CONFIG_GET(I2S_NL), PINCTRL_STATE_DEFAULT);
__ASSERT_NO_MSG(ret == 0);

IRQ_CONNECT(DT_IRQN(I2S_NL), DT_IRQ(I2S_NL, priority), nrfx_isr, nrfx_i2s_0_irq_handler, 0);
irq_enable(DT_IRQN(I2S_NL));

ret = nrfx_i2s_init(&i2s_inst, &cfg, i2s_comp_handler);
__ASSERT_NO_MSG(ret == NRFX_SUCCESS);

state = AUDIO_I2S_STATE_IDLE;
}

Now when I'm building this, I'm getting this weird error 
gen_isr_tables.py: error: multiple registrations at table_index 40 for irq 40 (0x28)
Existing handler 0x22407, new handler 0x22407
Has IRQ_CONNECT or IRQ_DIRECT_CONNECT accidentally been invoked on the same irq multiple times?

ninja: build stopped: subcommand failed.
 

I went through the Global Search to find if there are multiple instances of IRQ_CONNECT, but I found only 1 instance that is present in the audio_i2s_init() function in the code file which I have mentioned above. What could possibly cause this error and how do I fix it?

Also is there any other simpler way of setting up I2S service with both the CS47L63 Codec and the LC3 Codec?

Parents
No Data
Reply Children
  • Hello,

    I see, thank you for clarifying.

    SohamGhugare said:

    when I'm trying to set it up its giving me this error

    /opt/nordic/ncs/v2.6.0/modules/hal/nordic/nrfx/drivers/include/nrfx_timer.h:65:39: error: 'NRFX_TIMER1_INST_IDX' undeclared here (not in a function); did you mean 'NRFX_I2S0_INST_IDX'?

    .

    .

    audio_sync_timer.c:29:9: note: in expansion of macro 'NRFX_TIMER_INSTANCE'
    29 | NRFX_TIMER_INSTANCE(AUDIO_SYNC_TIMER_INSTANCE_NUMBER);

    Note that I copied the audio_sync_timer and audio_i2s header files as it is from the audio application 

    This seems to me like you are missing an enable kconfig option.
    Could you share your .conf file from the build in which this is happening?
    The file will be located at

    YOUR/PATH/build/zephyr/.conf

    This will allow me to check if this might be the issue here.

    Best regards,
    Karl

Related