Strange Behavior with MK22FN512

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Strange Behavior with MK22FN512

Jump to solution
1,005 Views
eduardoumana
Contributor III

I have a very strange situation happening. I am trying to build a simple PCB with an onboard I2S Microphone using the MK22FN512VLH12. I use DMA.

I have built two PCBs that are identical. The components on the PCBs are working and can do printf, switch LED, etc... However, only one of them can obtain data from the I2S microphone!!! You would say the microphone isn't working in the PCB that doesn't work, but I know for a fact the microphone is not the issue. This is confirmed by an oscilloscope and another successful program that doesn't use DMA and can read data from the microphone and output it. I have done some tests and it seems that in the PCB that is not working the program only enters the DMA0_IRQHandler exactly 1 time, in the PCB that works it access it every time new data is available.My program essentially sets up I2S, sets up DMA, and then uses the ARM DSP library to do some FFTs, nothing more. The I2S set-up seems to be working since I use that in the successful non-DMA program in the faulty unit. Here is a pic to prove it, the red PCB works, the Green and White doesn't:


WP_20150408_001.jpg


How can this be possible? Identical hardware, identical software, yet not the same behavior. Is it possible that when soldering something heated up too much and failed? Hard to believe since the faulty PCB seems to be able to do about everything but obtain data from the microphone. Here is all of my code:

#include "mbed.h"

#include <stdio.h>

#include <ctype.h>

#include <arm_math.h>

Serial pc(USBTX, USBRX);

DigitalOut led(PTD4);

DigitalOut CHIPEN(PTC11);

DigitalOut LR(PTC10);

int times = 0;

const int SAMPLE_RATE_HZ = 9000;

const int FFT_SIZE = 2048;

int32_t BUFFER_A[FFT_SIZE];

int32_t BUFFER_B[FFT_SIZE];

int32_t *DMA_BUFF;

int32_t *READ_BUFF;

float samples[FFT_SIZE*2];   

float magnitudes[FFT_SIZE*2]; 

bool SAMPLING_DONE = 0;

bool USING_BUFFER_A = 1;

void pr_16(volatile uint16_t *reg);

void pr(volatile uint32_t *reg);

void START_I2S();

void START_DMA();

void RX_CALL();

void checkRequest();

void sendData(int dataType);

extern "C" void DMA0_IRQHandler();

int main(){

   

    pc.baud(230400);

    START_I2S();

    START_DMA();

    led = 1;

   

   

    while(1){

       

        pc.printf("%i\r\n",times);

       

        if(SAMPLING_DONE){

            times++;

            unsigned short j = FFT_SIZE;

            while(j--){

                samples[j] = (float) READ_BUFF[j]/100000; //100000

            }

           

            arm_rfft_fast_instance_f32 fft_inst;

            arm_rfft_fast_init_f32(&fft_inst, FFT_SIZE);

            arm_rfft_fast_f32(&fft_inst, samples, magnitudes, 0);           

            arm_cmplx_mag_squared_f32(magnitudes, magnitudes, FFT_SIZE);

           

            SAMPLING_DONE = 0; 

            //checkRequest();        

        }  

    }    

}

//I2S Init

void START_I2S(){

    CHIPEN = 1;

    LR = 0;

    //Pins Init

    SIM_SCGC5  |= 0x42B82;          //Enables PORTC

    PORTC_PCR5 |= 0x400;            //PTC5 --> I2S0_RXD0 -> SD

    PORTC_PCR6 |= 0x400;            //PTC6 --> I2S0_RC_BCLK -> SCK

    PORTC_PCR7 |= 0x400;            //PTC7 --> I2S0_RX_FS -> WS

    //Clock Init

    SIM_SCGC6 |= 0x8000;            //Turn on I2S Clock Gate

    SIM_SOPT2 |= 0x30000;           //I2S Clocking Sourced from 48MHz IRC48MCLK

    I2S0_MCR  |= 0x43000000;        //Output Enable. Mux IRC48MCLK into Fractional Divider

    I2S0_RCR2 |= 0x700000D;         //MCLK MSEL to BCLK. Div -> 13, 9k Sample

    I2S0_MDR  |= 0x1F07C;           //Set I2S Master Clock to 12.2880MHz

    SIM_SCGC6 |= 0x8000;            //Re-Enable I2S Module

    //Receive Init

    I2S0_RCSR  = 0x0;               //Disable Receive as per Datasheet

    I2S0_RCR1 |= 0x1;               //Sets FIFO Watermark to 1

    I2S0_RCR3 |= 0x10000;           //Enable Receive Data Channel

    I2S0_RCR4 |= 0x10011F1B;        //Internal FS. Early FS. 32 SYWD. FRSZ 2. FCONT

    I2S0_RCR5 |= 0x1F1F1F00;        //32 Bits per Word. 32 Bits in First Word. Shifted 32.

    I2S0_RMR  |= 0x2;               //Mask 2nd Word (One Channel Only)

   

    I2S0_RCSR |= 0x80000001;        //Enable & Request DMA  

}

//DMA Init

void START_DMA(){

   

    SIM_SCGC6 |= 0x2;               //DMAMUX Module Turn On

    SIM_SCGC7 |= 0x2;               //DMA Module Turn On

    DMAMUX_CHCFG0 = 0x8C;           //I2S Source: Slot 12 & Activate   

   

    DMA_TCD0_CSR &= 0xBF;           //Inactive

    NVIC_EnableIRQ(DMA0_IRQn);      //Enable IRQ DMA Channel 0

    DMA_TCD0_CSR |= 0x2;            //Interrupt Major Iteration

    DMA_CR = 0x0;                   //Disable

       

    DMA_TCD0_SADDR = (uint32_t) &I2S0_RDR0;     //Data Source

    DMA_TCD0_DADDR = (uint32_t) BUFFER_A;       //Destination

   

    DMA_TCD0_SOFF = 0;                          //No Source Offset

    DMA_TCD0_SLAST = 0;                         //Nothing Added to Source Address after Major Loop

    DMA_TCD0_DLASTSGA = -(FFT_SIZE*4);          //Value Added to Destination Address after Major Loop

    DMA_TCD0_DOFF = 4;                          //4 Byte Destination Offset

    DMA_TCD0_NBYTES_MLNO = 4;                   //4 Bytes Transfered in Minor Loop

    DMA_TCD0_BITER_ELINKNO = FFT_SIZE;          //1024 Bins  

    DMA_TCD0_CITER_ELINKNO = FFT_SIZE;          //1024 Bins

    DMA_TCD0_ATTR = 0x202;                      //32-Bit Transfer Size

   

    DMA_SERQ = 0x0;                             //Channel 0 Enable

    DMA_TCD0_CSR |= 0x41;                       //Enable!

}

//RX Interrupt Callback

void RX_CALL(){

  

    if(USING_BUFFER_A){

       USING_BUFFER_A = 0;

       DMA_BUFF = BUFFER_B;

       READ_BUFF = BUFFER_A;

    }

    else{

        USING_BUFFER_A = 1;

        DMA_BUFF = BUFFER_A;

        READ_BUFF = BUFFER_B;    

    } 

    DMA_TCD0_DADDR = (uint32_t) DMA_BUFF;

}

//DMA 0 Interrupt Handler

extern "C" void DMA0_IRQHandler(){

    DMA_CINT = 0;

    SAMPLING_DONE = 1;

    RX_CALL();

    return;

}

//Debugging tool, it prints register [address]--> [contents]

//Pass the "address of" a register, i.e: pr(&PORTA_PCR1)

void pr_16(volatile uint16_t *reg) {

    pc.printf("%x --> %u \r\n", reg, *reg);

}

//32-Bit

void pr(volatile uint32_t *reg) {

    pc.printf("%x --> %x \r\n", reg, *reg);

}

/* MATLAB Serial Com.

* 1. Sends Magnitudes

* 2. Sends Samples

* 3. Sends FFT Size

* 4. Sends Sample Rate

*/

void sendData(int dataType) {

  if (dataType == 1) {

    for (int i = 1; i < (FFT_SIZE/2) + 1; ++i) {

      pc.printf("%f\n", magnitudes[i]);

    }

  }

  else if (dataType == 2) {

    for (int i = 0; i < FFT_SIZE; ++i) {

     pc.printf("%f\n", samples[i]);

    }

  }

  else if (dataType == 3) {

   pc.printf("%d\n", FFT_SIZE);

  }

  else if (dataType == 4) {

   pc.printf("%d\n", SAMPLE_RATE_HZ);

  }

}

//Checks If MATLAB needs Data

void checkRequest(){

    int number;

    pc.scanf("%d", &number);    

    sendData(number);

}

Tags (3)
1 Solution
595 Views
eduardoumana
Contributor III

Got it! If it's not the hardware, and it's not the software, it must be some sort of initial state. The DMA_TCD0_CSR register has different initial values on each PCB, making only one of them work. The solution was initializing the register to 0. Now the question is, is this normal behavior?

View solution in original post

0 Kudos
3 Replies
595 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,Eduardo,

Regarding your code,  DMA_TCD0_CSR |= 0x41; because you use I2S0 to trigger DMA, I do not think it is necessary to set the START bit in CSR register.

Regarding the issue, I suggest you check the DMA_ES register, it lists the error flag, it the DMA works fine, it should be zero.

Hope it can give you clue
BR

XiangJun Rong

0 Kudos
595 Views
eduardoumana
Contributor III

Thank you XiangJun. It seems that in both PCBs the SGE and SBE error flags are thrown. But why does one PCB work and the other doesn't? And what could be the error?

Edit: Could it be that each micro controller has different initial value bits on reset? The hardware is not the problem and neither is the software... This is really strange.

0 Kudos
596 Views
eduardoumana
Contributor III

Got it! If it's not the hardware, and it's not the software, it must be some sort of initial state. The DMA_TCD0_CSR register has different initial values on each PCB, making only one of them work. The solution was initializing the register to 0. Now the question is, is this normal behavior?

0 Kudos