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

I2S - Unable to generate MCK and SCK on nRF 52 board

Hi,

I'm new to embedded development and am trying to interface a 24-bit MEMS microphone (Invensense ICS-43432) using I2S with nRF52 Dev board (PCA10040, V 0.9.0, 2015.39).

Also, I'm using this nRF52 SDK (version 0.9.2).

I am unable to detect (using an Oscilloscope) any signal at Pins 00, 01 and 02 (on nRF 52 dev board) after running the following code. Also, I'm using Eclipse IDE for C/C++ to run/connect/debug this program.

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "config.h"
#include "app_uart.h"
#include "nrf_gpio.h"
#include "app_error.h"
#include "nrf.h"
#include "bsp.h"
#include "app_util_platform.h"
#include "SEGGER_RTT.h"

#define I2S_BUFFER_SIZE  5
static uint32_t rxBufferOne[I2S_BUFFER_SIZE] = {0};

int main(void) {
    //Mode - Enable Master Mode
	NRF_I2S->CONFIG.MODE = (I2S_CONFIG_MODE_MODE_MASTER <<I2S_CONFIG_MODE_MODE_Pos);
	// Enable reception
	NRF_I2S->CONFIG.RXEN = (I2S_CONFIG_RXEN_RXEN_ENABLE << I2S_CONFIG_RXEN_RXEN_Pos);
	// Enable MCK generator - (Clock for the external sensor)
	NRF_I2S->CONFIG.MCKEN = (I2S_CONFIG_MCKEN_MCKEN_ENABLE << I2S_CONFIG_MCKEN_MCKEN_Pos);
	// MCKFREQ = 1.0322581 MHz
	NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV31 << I2S_CONFIG_MCKFREQ_MCKFREQ_Pos;
	// Ratio = 512
	NRF_I2S->CONFIG.RATIO = I2S_CONFIG_RATIO_RATIO_512X << I2S_CONFIG_RATIO_RATIO_Pos;
    
	// Sample width = 24 bit
	NRF_I2S->CONFIG.SWIDTH = I2S_CONFIG_SWIDTH_SWIDTH_24BIT << I2S_CONFIG_SWIDTH_SWIDTH_Pos;

	// MCKFREQ = 1.0322581 MHz and Ratio = 512 gives sample rate 1032258.1/512 = 2.016129 ks/s
	// 24 * sample rate = bits per second / channel ==> 48.4 kbps ==> 6.1 KBps

	// Alignment = Left
	NRF_I2S->CONFIG.ALIGN = I2S_CONFIG_ALIGN_ALIGN_LEFT << I2S_CONFIG_ALIGN_ALIGN_Pos;
	// Format = I2S
	NRF_I2S->CONFIG.FORMAT = I2S_CONFIG_FORMAT_FORMAT_I2S << I2S_CONFIG_FORMAT_FORMAT_Pos;
	// Use one channel only (Left Channel)
	NRF_I2S->CONFIG.CHANNELS = I2S_CONFIG_CHANNELS_CHANNELS_LEFT << I2S_CONFIG_CHANNELS_CHANNELS_Pos;

	// MCK routed to pin 0
	NRF_I2S->PSEL.MCK = (0 << I2S_PSEL_MCK_CONNECT_Pos) |
	                    (I2S_PSEL_MCK_CONNECT_Connected << I2S_PSEL_MCK_CONNECT_Pos);
	// SCK routed to pin 1 (SCK on the Sensor Breakout board)
	NRF_I2S->PSEL.SCK = (1 << I2S_PSEL_SCK_CONNECT_Pos) |
	                    (I2S_PSEL_SCK_CONNECT_Connected << I2S_PSEL_SCK_CONNECT_Pos);
	// LRCK routed to pin 2 (WS on the Sensor Breakout board)
	NRF_I2S->PSEL.LRCK = (2 << I2S_PSEL_LRCK_CONNECT_Pos) |
	                     (I2S_PSEL_LRCK_CONNECT_Connected << I2S_PSEL_LRCK_CONNECT_Pos);
	// SDIN routed on pin 4  (SD on the Sensor Breakout board)
	NRF_I2S->PSEL.SDIN = (4 << I2S_PSEL_SDIN_CONNECT_Pos) |
	                     (I2S_PSEL_SDIN_CONNECT_Connected << I2S_PSEL_SDIN_CONNECT_Pos);

	NRF_I2S->RXD.PTR = (uint32_t) rxBufferOne;
	NRF_I2S->RXTXD.MAXCNT = I2S_BUFFER_SIZE;

	//Enable the I2S module using the ENABLE register
	NRF_I2S->ENABLE = 1;

	//Start audio streaming using the START task
	NRF_I2S->TASKS_START = 1;

    while(1) {
    	if(NRF_I2S->EVENTS_RXPTRUPD != 0)	{
    		SEGGER_RTT_printf(0, "MAXCNT: %d\r\n", NRF_I2S->RXTXD.MAXCNT);

    		for (int i=0; i<I2S_BUFFER_SIZE; i++) {
    			SEGGER_RTT_printf(0, "%lu\r\n", (unsigned long) rxBufferOne[i]);
    		}
    		memset(&rxBufferOne, 0, sizeof (rxBufferOne));
    		NRF_I2S->EVENTS_RXPTRUPD = 0;    
    	}
    }
}

I tried both:

  1. Checked for signals on pins 0,1 & 2 without connecting anything to the nRF52 dev board.
  2. Checked for signals on pins 0,1 & 2 after connecting the appropriate pins to the MEMS microphone.

The above code is copied from the I2S section of nRF52832 PS.

Would you look at the above code and tell me if I'm missing anything? How can I ensure that the external MEMS microphone gets the clock signal?

What are the characteristics (pulse height, pulse width, etc.) of the expected MCK/SCK?

Also, I understand that you were planning to release the new version of the nRF52 SDK with the example/driver for i2S about a month ago. Is that going to be released soon?

Thanks, Shashi

  • Hi Aryan,

    Thank you for looking in to this.

    Yes. I've spent a lot of time trying to get this working on nRF52. At this point, is there anything you can do to help resolve this issue? I'm thinking of giving up on nRF52. Do you have any ETA for the 1.0 version of nRF52 SDK and the example/driver for i2S? Does the above code look right? Do I have to use the low-level API to work with i2S?

    Thanks again.

    Cheers, Shashi

  • I think you would probably want to use some other GPIO pins than 0 and 1 since they are used by the crystal on the NRF52 DK board. Check the backside of the board to see which pins are already in use by the board.

  • Hi, I had what I think is the same problem with a Knowles microphone(SPH0645LM4H-B). A similar question(duplicate?) is located here

    And I think that we are all struggling with these two conditions from the product specification:

    When configuring these registers, the user is responsible for fulfilling the following requirements:
    
      1. SCK frequency can never exceed the MCK frequency, which can be formulated as:
    
          CONFIG.RATIO >= 2 * CONFIG.SWIDTH
    
      2. The MCK/LRCK ratio shall be a multiple of 2 * CONFIG.SWIDTH, which can be formulated as:
    
          Integer = (CONFIG.RATIO / (2 * CONFIG.SWIDTH))
    

    We all have a microphone that has a bit width of 24, that excludes all ratio settings except for 48,96,192,384. The SCL/LRCLK is required from the datasheet to be 64, but the only ratio from these settings are 48.

    Please correct me if I am wrong, I would really like to get my microphone up and running.

Related