DMA with SPI on KL25z with mlx camera

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

DMA with SPI on KL25z with mlx camera

1,220 Views
lucasmahieu
Contributor III

Hey, 

I try to make a communication between the spi of kl25z and  mlx camera.

I have to get the data thanks to DMA.

With oscilloscope I succeed to see that I send the right command byte to the mlx.

 

I receive some data from the mlx, but I don't succeed to get it. 

 

Can you look at my dam_init, because the software is blocking on the "enable_irq(INT_DMA0 - 16);" fonction call.

 

void dma_init(void){

new_dma_data=0;
// Enable clocks
SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;

// Config DMA Mux for ADC operation
// Disable DMA Mux channel first
DMAMUX0_CHCFG0 = 0x00;

 

// Configure DMA
DMA_SAR0 = (uint32_t) &SPI0_D;
DMA_DAR0 = (uint32_t) spi_rdata;
DMA_DSR_BCR0 = DMA_DSR_BCR_BCR(3); // transfert de 3 octets via le DMA

DMA_DCR0 |= (DMA_DCR_EINT_MASK| // Enable interrupt
DMA_DCR_ERQ_MASK | // Enable peripheral request
DMA_DCR_SSIZE(1) | // Set source size to 8 bits
DMA_DCR_DINC_MASK| // Set increments to destination address
DMA_DCR_DSIZE(1)); // Set destination size of 8 bits 


// Enable DMA channel and source
DMAMUX0_CHCFG0 |= DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_SOURCE(16); // Enable DMA channel and set SPI0 receive as source cf doc KL25P80M48SF0RM.pdf p64-65


// Enable interrupt
enable_irq(INT_DMA0 - 16);
}

 

thanks in advance 

 

lucas

Labels (1)
Tags (3)
0 Kudos
5 Replies

885 Views
lucasmahieu
Contributor III

I am confused because I do't succeed to make my SPI connection working with DMA... 

You gave me so many advice, but I steel have problems.

here my code : 

The main.c

int main(void){
     volatile int it = 0;

     dma_init();

     for(it=0;it <100000;it++);

     SPI_init();

     camera_send_cmd(CR,0,0);

     for(it=0;it <100000;it++);

     camera_send_cmd(WU,0,0);

     TERMINAL_PRINTF("START TEST\n\r");

     while(1) {

          test_RT();

          for(it=0;it <100000;it++);
     }
     return 0;
}

 

 

The test_RT fonction: 

extern uint8_t spi_rdata[3]={0xf};
#define RT 0b11000011
void test_RT(){
     volatile int i=0;
     uint8_t read[3]={RT,0x00,0x00};
     TERMINAL_PRINTF("TEST_RT - new_dma_data=%u\n\r",new_dma_data);
     
        SPI_write(read,3);

     for(i=0;i<1000000;i++);

     if(new_dma_data){
          TERMINAL_PRINTF("SB=%u\n\r",spi_rdata[0]);
          TERMINAL_PRINTF("Threshold=%u\n\r",spi_rdata[1]);
          TERMINAL_PRINTF("Zero=%u\n\r",spi_rdata[2]);
          TERMINAL_PRINTF("----------------\n\r");
     }
}

 

I will give you me 2 init fonction : 

 

volatile uint8_t new_dma_data=0;

void DMA_IRQHandler(void){
     static uint8_t nb_int = 0;
     nb_int =;
     if(nb_int%3==0){
       // Clear pending errors and/or the done bit 
       if (((DMA_DSR_BCR0 & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK)
               | ((DMA_DSR_BCR0 & DMA_DSR_BCR_BES_MASK) == DMA_DSR_BCR_BES_MASK)
               | ((DMA_DSR_BCR0 & DMA_DSR_BCR_BED_MASK) == DMA_DSR_BCR_BED_MASK)
               | ((DMA_DSR_BCR0 & DMA_DSR_BCR_CE_MASK) == DMA_DSR_BCR_CE_MASK))
          DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK;

       DMA_SAR0 = (uint32_t) &SPI0_D;
       DMA_DAR0 = (uint32_t) &spi_rdata;
       DMA_DSR_BCR0 |= DMA_DSR_BCR_BCR(3);
       DMA_DCR0 |= DMA_DCR_ERQ_MASK;

       new_dma_data++;
     }
     TERMINAL_PRINTF("IRQ_DMA\n");
}

void dma_init(void){

     new_dma_data=0;
     // Enable clocks
     SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
     SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;

     // Config DMA Mux for ADC operation
     // Disable DMA Mux channel first
     DMAMUX0_CHCFG0 = 0x00;

     // Clear pending errors and/or the done bit 
     if (((DMA_DSR_BCR0 & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK)
               | ((DMA_DSR_BCR0 & DMA_DSR_BCR_BES_MASK) == DMA_DSR_BCR_BES_MASK)
               | ((DMA_DSR_BCR0 & DMA_DSR_BCR_BED_MASK) == DMA_DSR_BCR_BED_MASK)
               | ((DMA_DSR_BCR0 & DMA_DSR_BCR_CE_MASK) == DMA_DSR_BCR_CE_MASK))
          DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK;

     // Configure DMA
     DMA_SAR0 = (uint32_t) &SPI0_D;
     DMA_DAR0 = (uint32_t) &spi_rdata;
     DMA_DSR_BCR0 = DMA_DSR_BCR_BCR(3); // transfert de 3 octets via le DMA

     // Clear Source size and Destination size fields.  
     DMA_DCR0 &= ~(DMA_DCR_SSIZE_MASK | DMA_DCR_DSIZE_MASK);

     DMA_DCR0 |= DMA_DCR_DSIZE(1);     // Set destination size of 8 bits 
     DMA_DCR0 |= DMA_DCR_SSIZE(1);     // Set source size to 8 bits
     DMA_DCR0 |= DMA_DCR_DINC_MASK;     // Set increments to destination address
     DMA_DCR0 |= DMA_DCR_DMOD(1);     // destination adress modulo 16 bytes
     DMA_DCR0 |= DMA_DCR_CS_MASK;     // 1 transfert per request 
     DMA_DCR0 |= DMA_DCR_EINT_MASK;     // Enable interrupt

     // Enable DMA channel and source
     // Enable DMA channel and set SPI0 receive as source cf doc KL25P80M48SF0RM.pdf p64-65
     DMAMUX0_CHCFG0 |= DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_SOURCE(16); 

     DMA_DCR0 |= DMA_DCR_ERQ_MASK; // Enable peripheral request

     // Enable interrupt
     enable_irq(INT_DMA0 - 16);
}

 

and for the spi :

 

uint8_t spi_rdata[3]={0xFF};

void SPI_init(void) {
     // Enable clock network to SPI0
     SIM_SCGC4 |= SIM_SCGC4_SPI0_MASK;
     SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK;
     SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK;
     
     PORTD_PCR0 = PORT_PCR_MUX(2);  // PCS
     PORTC_PCR5 = PORT_PCR_MUX(2);  // SCK
     PORTC_PCR6 = PORT_PCR_MUX(2);  // MOSI
     PORTC_PCR7 = PORT_PCR_MUX(2);  // MISO
     
     // disable SPI
     SPI0_C1 &= ~SPI_C1_SPE_MASK;

     SPI0_C1 = SPI_C1_MSTR_MASK | SPI_C1_SSOE_MASK | SPI_C1_CPHA_MASK | SPI_C1_CPOL_MASK;   
     
     SPI0_C2 = SPI_C2_MODFEN_MASK;   //Master SS pin acts as slave select output     

     // Pour activer le DMA en réception
     SPI0_C2 |= SPI_C2_RXDMAE_MASK;

     SPI0_BR = (SPI_BR_SPPR(0b000) | SPI_BR_SPR(0b0011));     
     
     SPI0_C1 |= SPI_C1_SPE_MASK;          /* Enable SPI module */
}

void SPI_write(uint8_t* p, uint8_t size) {
     uint8_t i=0;
     for (i=0; i<size; i++) {
          while(!(SPI_S_SPTEF_MASK & SPI_status));
          SPI0_D = p[i];
     }
}

 

sorry for the french comment in the code ^^

 

I give you lot of work, but your help would be very very very useful because I really donc understand what is the problem.

 

I use an oscilloscope to see the signal. All signal are right the MOSI, the MISO also.

 

BUT : 

-> if the interrupt of the DMA is disable (DMA_DCR_EINT_MASK not used), all works fine. But I receive 0 in spi_rdata[0], 0 in spi_rdata[1], 0 in spi_rdata[2]. I initialise spi_rdata[] with 0xFF, and in the printf I can see that there are 0 in spi_rdata[i]. But the problem is that on MISO I don't have 0 ... So Why ? Really don't understand this point.

 

-> if I enable the interrupt in the DMA init : the spi_write() is blocking. The program block in the spi_write fonction I donc know why ... 

 

REALLY thanks in advance ! 

0 Kudos

885 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Mahieu,

1. Please delete the following code in dma initial:

     DMA_DCR0 |= DMA_DCR_DMOD(1);     // destination adress modulo 16 bytes

2.  You said when DMA interrupt is disabled, the receive data is 0, and the MISO is not 0, what the data in the MISO line?

  You can post some wave picture.

  About the code testing in the main, you can use break point to test :



void SPI_write(uint8_t* p, uint8_t size) {
     uint8_t i=0;
     for (i=0; i<size; i++) {
          while(!(SPI_S_SPTEF_MASK & SPI1_S));
          SPI0_D = p[i];
     }
}


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

885 Views
lucasmahieu
Contributor III

Hey kerry, 

At first REALY thanks you for your reply ! 

1 : 

DMA_DCR0 |= DMA_DCR_DMOD(1);     // destination adress modulo 16 bytes

Ok,it is removed 

I have checked all wire on me dev board and the kl25z, I have checked my code thanks to you,

and it works !!!!!!!!!!!

I am really really happy to succeed. Thanks again.

For now I can receive several time 3 bytes through the spi + dma.

But I steal have a problem, The interrupt of the dma doen't work.

I had this line in the dma configuration



// Enable interrupt
     enable_irq(INT_DMA0 - 16);
I think this line is the problem.
But I never have any interrupt a the end of the DMA BCR = 0. Do you have an idea ? according to me code posted here ? Best reagard, and thanks again
0 Kudos

885 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi mahieu,  

 Enable interrupt code should be:

    enable_irq(0);

Because your INT_DMA0 =16, then

enable_irq(INT_DMA0 - 16);

is correct.

  You can put an break point in the ISR, check whether the code enter it.

  Besides, don't do clear DMA done code in your main code, after send and receive the data, check the DONE bit, whether it is set.


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

885 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi mahieu lucas,

    I have attached a kl25 spi dma project for your reference.

   The code function is use DMA send the SRAM address 0x20000010 data to SPI , use DMA receive the data from SPI , and transfer it to the SRAM address 0x20000000.

   This code works on my side, you can refer to it.

Wish it helps you!

If you still have question, please contact me!


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos