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,

    Oh, then I must have misunderstood you earlier - I thought you were working in the nRF5340 LE Audio reference application.
    Could you share your project with me here?
    It could for instance be that you are initializing I2S as part of your prj.conf, while the audio_i2s driver might also do an init through direct calls to the nrfx i2s driver's init function.
    Could this for instance be the case here?

    Best regards,
    Karl

Related