This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

There is a problem adding I2S code.

Hello

I am using nrf52832 and sdk v17.0
I recently succeeded in controlling several ws2812 LEDs through I2S. And now I'm going to combine these codes with the others.

However, when I debug the combined code, 'i2s_init()' outputs the following error:

<error> app: ERROR 3735928559 [Unknown error code] at ../../../../../../modules/nrfx/hal/nrf_gpio.h:492
PC at: 0x00033413


//nrf_gpio.h  492line
__STATIC_INLINE NRF_GPIO_Type * nrf_gpio_pin_port_decode(uint32_t * p_pin)
{
    NRFX_ASSERT(nrf_gpio_pin_present_check(*p_pin)); //<< error
#if (GPIO_COUNT == 1)
    return NRF_P0;
#else
    if (*p_pin < P0_PIN_NUM)
    {
        return NRF_P0;
    }
    else
    {
        *p_pin = *p_pin & 0x1F;
        return NRF_P1;
    }
#endif
}

This is the code I used to control led with i2s.

/** @file
 * @defgroup i2s_example_main main.c
 * @{
 * @ingroup i2s_example
 *
 * @brief SK6812 I2S Example Application main file.
 *
 * This file contains the source code for a sample application using I2S with SK6812 LEDs.
 */

#include <stdio.h>
#include "nrf_drv_i2s.h"
#include "nrf_delay.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "boards.h"

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#define LED_DIN_PIN		    15//27 //2
#define LED_LRCK_PIN		    11
#define LED_SCK_PIN		    18
#define NUM_LEDS		    3 //9
#define DATA_BYTES_PER_LED	    3	// 24-bit GRB data structure
#define LEDS_DATA_BYTE_SIZE	    NUM_LEDS * DATA_BYTES_PER_LED //LEDs * (8bit * 3 = 24bit)

#define I2S_BITS_PER_DATA_BIT	    4

//SK68xx LED
#define I2S_SK6812_ZERO		    0x8		//0b'1000 (0.3us; 0.9us)
#define I2S_SK6812_ONE		    0xC		//0b'1100 (0.6us; 0.6us)

//WS28xx LED
#define I2S_WS2812B_ZERO	    0x8		//0b'1000 (0.4us; 0.85us)
#define I2S_WS2812B_ONE		    0xE		//0b'1110 (0.8us; 0.45us)

#define I2S_BYTES_PER_RESET	    256/8	//reset_pulse / period = 80us / 0.3125us = 256
#define I2S_LEDS_WORD_SIZE	    BYTES_TO_WORDS(LEDS_DATA_BYTE_SIZE * I2S_BITS_PER_DATA_BIT)
#define I2S_RESET_WORD_SIZE	    BYTES_TO_WORDS(I2S_BYTES_PER_RESET)	//8 words
#define I2S_LEDS_FRAME_WORD_SIZE    I2S_LEDS_WORD_SIZE + I2S_RESET_WORD_SIZE

typedef struct { //LED colors
    uint8_t g;
    uint8_t r;
    uint8_t b;
} sk6812_led_t;

sk6812_led_t	m_led_buffer_tx[NUM_LEDS];
uint32_t	m_i2s_led_buffer_tx[I2S_LEDS_FRAME_WORD_SIZE];
//sk6812_led_t *p_led_buffer_tx;
//uint32_t *p_i2s_led_buffer_tx;


/**
 * @brief Clears the LED and I2S data buffers 
 */
ret_code_t sk6812_i2s_init_mem() {
// TODO: dynamically allocate memory when needed instead of using global arrays
//    // Init memory for LED data
//    if (p_led_buffer_tx) free(p_led_buffer_tx);
//    p_led_buffer_tx = (sk6812_led_t *)malloc(LEDS_DATA_BYTE_SIZE);
//    if (p_led_buffer_tx) memset(p_led_buffer_tx, 0, LEDS_DATA_BYTE_SIZE);
//    else return NRF_ERROR_NO_MEM;
//    
//    // Init memory for I2S data
//    if (p_i2s_led_buffer_tx) free(p_i2s_led_buffer_tx);
//    p_i2s_led_buffer_tx = (uint32_t *)malloc(I2S_LEDS_WORD_SIZE * 4);
//    if (p_i2s_led_buffer_tx) memset(p_i2s_led_buffer_tx, 0, I2S_LEDS_WORD_SIZE * 4);
//    else return NRF_ERROR_NO_MEM;
    
    // Reset data buffers, memory value and size
    memset(m_led_buffer_tx, 0, sizeof(m_led_buffer_tx)); 
    memset(m_i2s_led_buffer_tx, 0, sizeof(m_i2s_led_buffer_tx));
    
    return NRF_SUCCESS;
}


/**
 * @brief Stops data transfer after the first full transmission (only using single buffer)
 * @brief Handles transmitted data when receiving the TXPTRUPD and RXPTRUPD events, every RXTXD.MAXCNT number of transmitted data words
 * @brief Addresses written to the pointer registers TXD.PTR and RXD.PTR are double-buffered in hardware, and these double buffers are updated for every RXTXD.MAXCNT words
 */
void data_handler(nrf_drv_i2s_buffers_t const * p_released, uint32_t status) 
{
//    NRF_LOG_DEBUG("status: %d; p_tx_buffer: 0x%08X; p_rx_buffer: 0x%08X", status, p_released->p_tx_buffer, p_released->p_rx_buffer);

    // 'nrf_drv_i2s_next_buffers_set' is called directly from the handler
    // each time next buffers are requested, so data corruption is not expected.
//    ASSERT(p_released);

    // When the handler is called after the transfer has been stopped
    // (no next buffers are needed, only the used buffers are to be
    // released), there is nothing to do.
    if (!(status & NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED)) { //No buffer data, nothing to do
        return;
    }

    // Stop data transfer after the first full transmission (only using single buffer)
    if (p_released->p_tx_buffer != NULL) {
//	nrf_drv_i2s_stop();
	nrf_drv_i2s_uninit();
    }
}


/**
 * @brief Initializes the I2S interface for ~3.2MHz clock for SK6812
 */
ret_code_t sk6812_i2s_init() {
    nrf_drv_i2s_config_t config;     //= NRF_DRV_I2S_DEFAULT_CONFIG;
    config.sck_pin	= LED_SCK_PIN;	// Don't set NRF_DRV_I2S_PIN_NOT_USED for I2S_CONFIG_SCK_PIN. (The program will stack.) 
    config.lrck_pin	= NRF_DRV_I2S_PIN_NOT_USED; //LED_LRCK_PIN; // I2S_CONFIG_LRCK_PIN
    config.mck_pin	= NRF_DRV_I2S_PIN_NOT_USED;
    config.sdout_pin	= LED_DIN_PIN;	// I2S_CONFIG_SDOUT_PIN
    config.sdin_pin	= NRF_DRV_I2S_PIN_NOT_USED;
    config.irq_priority = I2S_CONFIG_IRQ_PRIORITY;
    config.mode         = NRF_I2S_MODE_MASTER;
    config.format       = NRF_I2S_FORMAT_I2S;
    config.alignment    = NRF_I2S_ALIGN_LEFT;
    config.sample_width = NRF_I2S_SWIDTH_8BIT;
    config.channels     = NRF_I2S_CHANNELS_STEREO;
    config.mck_setup    = NRF_I2S_MCK_32MDIV5;
    config.ratio        = NRF_I2S_RATIO_32X;

    uint32_t err_code = nrf_drv_i2s_init(&config, data_handler);
//    APP_ERROR_CHECK(err_code);
    
    return err_code;
}


/**
 * @brief Convert a byte of LED data to a word of I2S data 
 * @brief 1 data bit   <--> 4 I2S bits
 * @brief 1 data byte  <--> 1 I2S word
 */
uint32_t convert_byte_to_i2s_bits(uint8_t data_byte) {
    uint32_t data_bits = 0;
    
    // Set data_bits based on MSB, then left-shift data_byte
    for (int ii=0; ii < 8; ii++) {
	data_bits |= ((data_byte & 0x80) ? I2S_SK6812_ONE : I2S_SK6812_ZERO) << ((8-1-ii) * 4); //SK68xx
	//data_bits |= ((data_byte & 0x80) ? I2S_WS2812B_ONE : I2S_WS2812B_ZERO) << ((8-1-ii) * 4); //WS28xx
	data_byte = data_byte << 1;
    }

    return data_bits;
}


/**
 * @brief Sets I2S data from converted LED data
 */
void set_i2s_led_data() { //each color data
    uint16_t jj = 0;
    for (uint16_t ii=0; ii < NUM_LEDS; ii++) {
	m_i2s_led_buffer_tx[jj] = convert_byte_to_i2s_bits(m_led_buffer_tx[ii].g);
	m_i2s_led_buffer_tx[jj+1] = convert_byte_to_i2s_bits(m_led_buffer_tx[ii].r);
	m_i2s_led_buffer_tx[jj+2] = convert_byte_to_i2s_bits(m_led_buffer_tx[ii].b);
	jj += 3;
    }
}
 

/**
 * @brief Initializes I2S and starts the data transfer
 * @brief Assumes data buffers have already been set
 */
void send_i2s_led_data() {
    // Configure the I2S module and map IO pins
    uint32_t err_code = sk6812_i2s_init();
    
    // Prevent starting a new data transfer if I2S already initialized
    if (err_code == NRF_SUCCESS) {
	// Configure TX data buffer
	nrf_drv_i2s_buffers_t const initial_buffers = {
	    .p_tx_buffer = m_i2s_led_buffer_tx,
	    .p_rx_buffer = NULL
	};
    
	// Enable the I2S module and start data streaming
	err_code = nrf_drv_i2s_start(&initial_buffers, I2S_LEDS_FRAME_WORD_SIZE+1, 0);
	APP_ERROR_CHECK(err_code);
    } else {
	// Reset to all I2S_SK6812_ZERO's
	memset(m_i2s_led_buffer_tx, 0x88, I2S_LEDS_WORD_SIZE * 4);
    }
}

void clear_leds() {
    // Set to all I2S_SK6812_ZERO's
    memset(m_i2s_led_buffer_tx, 0x88, I2S_LEDS_WORD_SIZE * 4);
    send_i2s_led_data();
}


/**
 * @brief Set an RGB LED color data in the global sk6812_led_t array
 */
void set_led_pixel_RGB(uint16_t pos, uint8_t r, uint8_t g, uint8_t b) {
    m_led_buffer_tx[pos].r = r;
    m_led_buffer_tx[pos].g = g;
    m_led_buffer_tx[pos].b = b;
}


/**
 * @brief Ported Adafruit NeoPixel paint animation functions
 */
// Fill the dots one after the other with a color
void color_wipe(uint8_t r, uint8_t g, uint8_t b, uint8_t ms_delay) {
    sk6812_i2s_init_mem();
    
    for(uint16_t ii=0; ii < NUM_LEDS; ii++) {
	set_led_pixel_RGB(ii, r, g, b);
	set_i2s_led_data();
	send_i2s_led_data();
	nrf_delay_ms(ms_delay);
    }
}

// Input a value 0 to 255 to get a color value
sk6812_led_t wheel(uint8_t wheel_pos) {
    sk6812_led_t color;
    wheel_pos = 255 - wheel_pos;
    
    if(wheel_pos < 85) {
	color.r = 255 - wheel_pos * 3;
	color.g = 0;
	color.b = wheel_pos * 3;
	return color;
    }
    
    if(wheel_pos < 170) {
	wheel_pos -= 85;
	color.r = 0;
	color.g = wheel_pos * 3;
	color.b = 255 - wheel_pos * 3;
	return color;	
    }
    
    wheel_pos -= 170;
    color.r = wheel_pos * 3;
    color.g = 255 - wheel_pos * 3;
    color.b = 0;
    return color;
}

void rainbow(uint16_t ms_delay) {
    uint16_t ii, jj;
    sk6812_led_t color;
    
    sk6812_i2s_init_mem();
    for (jj=0; jj < NUM_LEDS; jj++) {
	for (ii=0; ii < NUM_LEDS; ii++) {
	    color = wheel(((ii * 256 / NUM_LEDS) + jj) & 255);
	    set_led_pixel_RGB(ii, color.r, color.g, color.b);
	}
	set_i2s_led_data();
	send_i2s_led_data();
	nrf_delay_ms(ms_delay);
    }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbow_cycle(uint16_t ms_delay) {
    uint16_t ii, jj;
    sk6812_led_t color;
    
    sk6812_i2s_init_mem();
    for(jj=0; jj < 256*3; jj++) { // 3 cycles of all colors on wheel
	for(ii=0; ii < NUM_LEDS; ii++) {
	    color = wheel(((ii * 256 / NUM_LEDS) + jj) & 255);
	    set_led_pixel_RGB(ii, color.r, color.g, color.b);
	}
	set_i2s_led_data();
	send_i2s_led_data();
	nrf_delay_ms(ms_delay);
    }
}

// Theater-style crawling lights.
void theater_chase(uint8_t r, uint8_t g, uint8_t b, uint16_t ms_delay) {
    sk6812_i2s_init_mem();
    for (int jj=0; jj < 10; jj++) {  //do 10 cycles of chasing
	for (int qq=0; qq < 3; qq++) {
	    for (uint16_t ii=0; ii < NUM_LEDS; ii=ii+3) {
		set_led_pixel_RGB(ii+qq, r, g, b);	//turn every third pixel on
	    }
	    set_i2s_led_data();
	    send_i2s_led_data();

	    nrf_delay_ms(ms_delay);

	    for (uint16_t ii=0; ii < NUM_LEDS; ii=ii+3) {
		set_led_pixel_RGB(ii+qq, 0, 0, 0);	//turn every third pixel off
	    }
	}
    }
}

// Theater-style crawling lights with rainbow effect
void theater_chase_rainbow(uint16_t ms_delay) {
    sk6812_led_t color;
    sk6812_i2s_init_mem();
    for (int jj=0; jj < 256; jj++) {     // cycle all 256 colors in the wheel
	for (int qq=0; qq < 3; qq++) {
	    for (uint16_t ii=0; ii < NUM_LEDS; ii=ii+3) {
		color = wheel((ii+jj) % 255);
		set_led_pixel_RGB(ii+qq, color.r, color.g, color.b);   //turn every third pixel on
	    }
	    set_i2s_led_data();
	    send_i2s_led_data();

	    nrf_delay_ms(ms_delay);

	    for (uint16_t ii=0; ii < NUM_LEDS; ii=ii+3) {
		set_led_pixel_RGB(ii+qq, 0, 0, 0);	//turn every third pixel off
	    }
	}
    }
}

//========================================================================

void color_test1(uint8_t r, uint8_t g, uint8_t b) {
    //sk6812_i2s_init_mem();

    set_led_pixel_RGB(0, r, g, b);
    set_i2s_led_data();
    send_i2s_led_data();
}

void color_test2(uint8_t r, uint8_t g, uint8_t b) {
    //sk6812_i2s_init_mem();

    set_led_pixel_RGB(1, r, g, b);
    set_i2s_led_data();
    send_i2s_led_data();
}

void color_test3(uint8_t r, uint8_t g, uint8_t b) {
    //sk6812_i2s_init_mem();

    set_led_pixel_RGB(2, r, g, b);
    set_i2s_led_data();
    send_i2s_led_data();
}

//========================================================================

int main(void) {
    uint32_t err_code = NRF_SUCCESS;
    err_code = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(err_code);
    NRF_LOG_DEFAULT_BACKENDS_INIT();
    NRF_LOG_INFO("nRF52 I2S and SK6812 LED example started.");
    NRF_LOG_FLUSH();

    // Ported LED paint animations from Adafruit's Neopixel library
    // https://github.com/adafruit/Adafruit_NeoPixel/blob/master/examples/strandtest/strandtest.ino
    
    // Some example procedures showing how to display to the pixels:
    /*color_wipe(255, 0, 0, 50); // Red
    color_wipe(0, 255, 0, 50); // Green
    color_wipe(0, 0, 255, 50); // Blue    
    
    // Send a theater pixel chase in...
    theater_chase(127, 127, 127, 50); // White
    theater_chase(127, 0, 0, 50); // Red
    theater_chase(0, 0, 127, 50); // Blue
    rainbow(20);
    rainbow_cycle(20);
    theater_chase_rainbow(50); */

    //each position led multi control
   /* color_test1(0, 255, 0);
    nrf_delay_ms(1000);
    color_test2(0, 0, 255);
    nrf_delay_ms(1000);
    color_test3(255, 50, 0);
    nrf_delay_ms(3000); 

    clear_leds(); //led off */
    
    // Stop and uninitialize the I2S interface to reduce current consumption
//    nrf_drv_i2s_stop();
//    nrf_drv_i2s_uninit();

  for(;;)
  {
    color_test1(0, 255, 0);
    nrf_delay_ms(1000);
    color_test2(0, 0, 255);
    nrf_delay_ms(1000);
    color_test3(255, 50, 0);
    nrf_delay_ms(1000);

    sk6812_i2s_init_mem();
    clear_leds(); //led off
    nrf_delay_ms(1000);
  }
}

/** @} */

And I attach the combined code below. (It controls devices including LEDs with buttons and apps.)

pca10040,h

#ifndef PCA10040_H
#define PCA10040_H

#ifdef __cplusplus
extern "C" {
#endif

#include "nrf_gpio.h"

// LEDs definitions for PCA10040
#define LEDS_NUMBER    4

#define LED_START      17
#define LED_1          17
#define LED_2          18
#define LED_3          19
#define LED_4          20
#define LED_STOP       20

#define LEDS_ACTIVE_STATE 0

#define LEDS_INV_MASK  LEDS_MASK

#define LEDS_LIST { LED_1, LED_2, LED_3, LED_4 }

#define BSP_LED_0      LED_1
#define BSP_LED_1      LED_2
#define BSP_LED_2      LED_3
#define BSP_LED_3      LED_4

#define BUTTONS_NUMBER 1 //4

#define BUTTON_START   13
#define BUTTON_1       13
//#define BUTTON_2       14
//#define BUTTON_3       15
//#define BUTTON_4       16
#define BUTTON_STOP    13 //16
#define BUTTON_PULL    NRF_GPIO_PIN_PULLUP

#define BUTTONS_ACTIVE_STATE 0

//#define BUTTONS_LIST { BUTTON_1, BUTTON_2, BUTTON_3, BUTTON_4 }
#define BUTTONS_LIST { BUTTON_1 }

#define BSP_BUTTON_0   BUTTON_1
/*#define BSP_BUTTON_1   BUTTON_2
#define BSP_BUTTON_2   BUTTON_3
#define BSP_BUTTON_3   BUTTON_4
*/

#define RX_PIN_NUMBER  8
#define TX_PIN_NUMBER  6
#define CTS_PIN_NUMBER 7
#define RTS_PIN_NUMBER 5
#define HWFC           true

#define SPIS_MISO_PIN   28  // SPI MISO signal.
#define SPIS_CSN_PIN    12  // SPI CSN signal.
#define SPIS_MOSI_PIN   25  // SPI MOSI signal.
#define SPIS_SCK_PIN    29  // SPI SCK signal.

#define SPIM0_SCK_PIN   29  // SPI clock GPIO pin number.
#define SPIM0_MOSI_PIN  25  // SPI Master Out Slave In GPIO pin number.
#define SPIM0_MISO_PIN  28  // SPI Master In Slave Out GPIO pin number.
#define SPIM0_SS_PIN    12  // SPI Slave Select GPIO pin number.

#define SPIM1_SCK_PIN   2   // SPI clock GPIO pin number.
#define SPIM1_MOSI_PIN  3   // SPI Master Out Slave In GPIO pin number.
#define SPIM1_MISO_PIN  4   // SPI Master In Slave Out GPIO pin number.
#define SPIM1_SS_PIN    5   // SPI Slave Select GPIO pin number.

#define SPIM2_SCK_PIN   12  // SPI clock GPIO pin number.
#define SPIM2_MOSI_PIN  13  // SPI Master Out Slave In GPIO pin number.
#define SPIM2_MISO_PIN  14  // SPI Master In Slave Out GPIO pin number.
#define SPIM2_SS_PIN    15  // SPI Slave Select GPIO pin number.

// serialization APPLICATION board - temp. setup for running serialized MEMU tests
#define SER_APP_RX_PIN              23    // UART RX pin number.
#define SER_APP_TX_PIN              24    // UART TX pin number.
#define SER_APP_CTS_PIN             2     // UART Clear To Send pin number.
#define SER_APP_RTS_PIN             25    // UART Request To Send pin number.

#define SER_APP_SPIM0_SCK_PIN       27     // SPI clock GPIO pin number.
#define SER_APP_SPIM0_MOSI_PIN      2      // SPI Master Out Slave In GPIO pin number
#define SER_APP_SPIM0_MISO_PIN      26     // SPI Master In Slave Out GPIO pin number
#define SER_APP_SPIM0_SS_PIN        23     // SPI Slave Select GPIO pin number
#define SER_APP_SPIM0_RDY_PIN       25     // SPI READY GPIO pin number
#define SER_APP_SPIM0_REQ_PIN       24     // SPI REQUEST GPIO pin number

// serialization CONNECTIVITY board
#define SER_CON_RX_PIN              24    // UART RX pin number.
#define SER_CON_TX_PIN              23    // UART TX pin number.
#define SER_CON_CTS_PIN             25    // UART Clear To Send pin number. Not used if HWFC is set to false.
#define SER_CON_RTS_PIN             2     // UART Request To Send pin number. Not used if HWFC is set to false.


#define SER_CON_SPIS_SCK_PIN        27    // SPI SCK signal.
#define SER_CON_SPIS_MOSI_PIN       2     // SPI MOSI signal.
#define SER_CON_SPIS_MISO_PIN       26    // SPI MISO signal.
#define SER_CON_SPIS_CSN_PIN        23    // SPI CSN signal.
#define SER_CON_SPIS_RDY_PIN        25    // SPI READY GPIO pin number.
#define SER_CON_SPIS_REQ_PIN        24    // SPI REQUEST GPIO pin number.

#define SER_CONN_CHIP_RESET_PIN     11    // Pin used to reset connectivity chip


// Arduino board mappings
#define ARDUINO_SCL_PIN             27    // SCL signal pin
#define ARDUINO_SDA_PIN             26    // SDA signal pin
#define ARDUINO_AREF_PIN            2     // Aref pin
#define ARDUINO_13_PIN              25    // Digital pin 13
#define ARDUINO_12_PIN              24    // Digital pin 12
#define ARDUINO_11_PIN              23    // Digital pin 11
#define ARDUINO_10_PIN              22    // Digital pin 10
#define ARDUINO_9_PIN               20    // Digital pin 9
#define ARDUINO_8_PIN               19    // Digital pin 8

#define ARDUINO_7_PIN               18    // Digital pin 7
#define ARDUINO_6_PIN               17    // Digital pin 6
#define ARDUINO_5_PIN               16    // Digital pin 5
#define ARDUINO_4_PIN               15    // Digital pin 4
#define ARDUINO_3_PIN               14    // Digital pin 3
#define ARDUINO_2_PIN               13    // Digital pin 2
#define ARDUINO_1_PIN               12    // Digital pin 1
#define ARDUINO_0_PIN               11    // Digital pin 0

#define ARDUINO_A0_PIN              3     // Analog channel 0
#define ARDUINO_A1_PIN              4     // Analog channel 1
#define ARDUINO_A2_PIN              28    // Analog channel 2
#define ARDUINO_A3_PIN              29    // Analog channel 3
#define ARDUINO_A4_PIN              30    // Analog channel 4
#define ARDUINO_A5_PIN              31    // Analog channel 5

//digital pin
#define BUZZER          25 
#define Magnetic        24
#define Piezo           23 //ultrasonic pin
#define UVC_LED         22
#define Charge_CHG      20 //charge IC CHG pin(charging check)


#ifdef __cplusplus
}
#endif

#endif // PCA10040_H

6747.nRF5_SDK_17.0.0_9d13099.zip

 Can I know about this problem because the same problem occurs even if I erase the code of main() and run i2s and led code?

Thank you in advance.

Related