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?

Related