Hello,
I've been trying to get the nrfx_i2s driver working with Zephyr, on the cpuapp core of the nRF5340. After configuring the driver, setting CONFIG_NRFX_I2S in prj.conf, setting my nRF5340 device as master, and registering the interrupt, I have noticed that no matter what pin configuration I use, I can not get any output on any of the i2s configured pins. However, the i2s interrupt is consistently being triggered, as I can toggle LED0 on the dk per couple of the interrupt triggers.
Current setup:
OS: macOS Mojave
Development environment: Visual Studio Code + CLI with west build -p auto -b nrf5340dk_nrf5340_cpuapp to build and west flash to flash
Logic analyzer: Logic Pro 16, Logic 2 software
Hardware: nRF5340_dk
To recreate the issue, I have attached my current files below. Please let me know if there's anything I need to try on my end!
#SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.13.1)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(wheezer)
include_directories(inc)
target_sources(app PRIVATE
src/main.c
src/buttonLed.c)
#include <zephyr.h>
#include <nrfx_gpiote.h>
#define SW0 DT_GPIO_PIN(DT_ALIAS(sw0), gpios)
#define SW1 DT_GPIO_PIN(DT_ALIAS(sw1), gpios)
#define SW2 DT_GPIO_PIN(DT_ALIAS(sw2), gpios)
#define SW3 DT_GPIO_PIN(DT_ALIAS(sw3), gpios)
#define LED0 DT_GPIO_PIN(DT_ALIAS(led0), gpios)
#define LED1 DT_GPIO_PIN(DT_ALIAS(led1), gpios)
#define LED2 DT_GPIO_PIN(DT_ALIAS(led2), gpios)
#define LED3 DT_GPIO_PIN(DT_ALIAS(led3), gpios)
static void sw0_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
nrfx_gpiote_out_toggle(LED0);
}
static void sw1_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
nrfx_gpiote_out_toggle(LED1);
}
static void sw2_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
nrfx_gpiote_out_toggle(LED2);
}
static void sw3_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
nrfx_gpiote_out_toggle(LED3);
}
void button_init(void){
IRQ_CONNECT(DT_IRQN(DT_NODELABEL(gpiote)),
DT_IRQ(DT_NODELABEL(gpiote), priority),
nrfx_isr, nrfx_gpiote_irq_handler, 0);
nrfx_gpiote_in_config_t const in_config = {
.sense = NRF_GPIOTE_POLARITY_HITOLO,
.pull = NRF_GPIO_PIN_PULLUP,
.is_watcher = false,
.hi_accuracy = true,
.skip_gpio_setup = false,
};
nrfx_gpiote_in_init(SW0, &in_config, sw0_handler);
nrfx_gpiote_in_init(SW1, &in_config, sw1_handler);
nrfx_gpiote_in_init(SW2, &in_config, sw2_handler);
nrfx_gpiote_in_init(SW3, &in_config, sw3_handler);
nrfx_gpiote_in_event_enable(SW0, true);
nrfx_gpiote_in_event_enable(SW1, true);
nrfx_gpiote_in_event_enable(SW2, true);
nrfx_gpiote_in_event_enable(SW3, true);
}
void led_init(void){
nrfx_gpiote_init(0);
nrfx_gpiote_out_config_t const out_config = {
.action = NRF_GPIOTE_POLARITY_TOGGLE,
.init_state = 1,
.task_pin = true,
};
nrfx_gpiote_out_init(LED0, &out_config);
nrfx_gpiote_out_init(LED1, &out_config);
nrfx_gpiote_out_init(LED2, &out_config);
nrfx_gpiote_out_init(LED3, &out_config);
nrfx_gpiote_out_init(32, &out_config);
}
void led_toggle(int ledPin){
nrfx_gpiote_out_toggle(ledPin);
}
void buttonLed_init(void){
led_init();
button_init();
}
#define NRFX_I2S_ENABLED 1
#include <zephyr.h>
#include "buttonLed.h"
#include <nrfx_i2s.h>
#define BUFFER_SIZE 200
#define PING_BUFFER_DATA_READY 0
#define PONG_BUFFER_DATA_READY 1
uint32_t rxBufferPing[BUFFER_SIZE] = {0};
uint32_t rxBufferPong[BUFFER_SIZE] = {0};
uint32_t txBufferDummy[BUFFER_SIZE] = {'d', 'e', 'a', 'd', 'b', 'e', 'e', 'f'};
nrfx_i2s_buffers_t rx_buffer_ping = {
.p_rx_buffer = rxBufferPing,
.p_tx_buffer = txBufferDummy
};
nrfx_i2s_buffers_t rx_buffer_pong = {
.p_rx_buffer = rxBufferPong,
.p_tx_buffer = txBufferDummy
};
volatile int whichBuffer = PING_BUFFER_DATA_READY;
volatile int i = 0;
static void i2s_data_handler(nrfx_i2s_buffers_t const* p_released, uint32_t status){
// data corruption if p_released is null
i++;
if(i % 10000 == 0){
led_toggle(LED0);
i = 0;
}
nrfx_i2s_buffers_t* nextBuffer;
if(p_released == &rx_buffer_ping){
nextBuffer = &rx_buffer_pong;
whichBuffer = PING_BUFFER_DATA_READY;
}else{
nextBuffer = &rx_buffer_ping;
whichBuffer = PONG_BUFFER_DATA_READY;
}
nrfx_i2s_next_buffers_set(nextBuffer);
}
int main()
{
// sanity check
//buttonLed_init();
led_init();
IRQ_CONNECT(DT_IRQN(DT_NODELABEL(i2s0)),
DT_IRQ(DT_NODELABEL(i2s0), priority),
nrfx_isr, nrfx_i2s_irq_handler, 0);
// i2s format is unaligned, but alignment param is mandatory
// NOTE: change priority
// LRCK = MCK/Ratio
// SCK = LRCK * 2 * SWIDTH
// Ratio >= 2 * SWIDTH
// SWIDTH = 24
// Ratio = 96
// MCK = 761904.8
// LRCK = 7936.5 (audio sampling rate)
// SCK = 380952.4
nrfx_i2s_config_t p_config = {
.sck_pin = 10,
.lrck_pin = 33,
.mck_pin = 36,
.sdout_pin = 37,
.sdin_pin = 38,
.irq_priority = DT_IRQ(DT_NODELABEL(i2s0), priority),
.mode = 0,
.format = 0,
.alignment = 0,
.sample_width = 2,
.channels = 2,
.mck_setup = 16,
.ratio = 3
};
volatile nrfx_err_t err0 = nrfx_i2s_init(&p_config, i2s_data_handler);
irq_enable(DT_IRQN(DT_NODELABEL(i2s0)));
while(1){
int i_temp = i;
volatile nrfx_err_t err1 = nrfx_i2s_start(&rx_buffer_ping, BUFFER_SIZE, 0);
while(i_temp >= i){
}
nrfx_i2s_stop();
}
return 0;
}