Continious DMA with SPI1 TX k22

Showing results for 
Search instead for 
Did you mean: 

Continious DMA with SPI1 TX k22

Contributor IV

  Hello ,

In my project I send data to DAC through SPI. Also in the project i am using USB. Max samplrate of DAC is 1MHz, so if i use interrupt to load PUSHR of SPI i got stacked with USB.

 But there is a good news for me - i need only linear scan, so I can use timer that scans 16bit and DMA to load it to PUSHR. So i set up DMA_CH0 to load PIT_1 value to pushr and triggers on PIT0 each 1us. But the problem is that DMA works only 1 time even if i set up self-linking of the channel.

I can see if i start PUSHR load in the code, after the transmission ends DMA worked once to load PIT1_CVAL. And stops untill i call PUSHR write once again.

My basic pices of code is below:

void ini_dma()
    const edma_config_t dma_conf={
//            .enableContinuousLinkMode=1,
    DMAMUX_EnableChannel(DMAMUX0,dma_ch_0); //dmamux =1 (PIT_CH0)

    EDMA_Init(DMA0, &dma_conf);
    uint16_t abc=32000;
    DMA0->TCD[0].SADDR = (int)&(PIT->CHANNEL[1].CVAL);
//    DMA0->TCD[0].SADDR = (int)&(abc);
    DMA0->TCD[0].SOFF= 0; /* no address shift after each transfer */
    DMA0->TCD[0].SLAST = 0;
    DMA0->TCD[0].DADDR = (int)&(SPI1->PUSHR);
    DMA0->TCD[0].DOFF= 0;
    DMA0->TCD[0].DLAST_SGA= 0;
    DMA0->TCD[0].NBYTES_MLNO=2; //2bytes for 16bit PUSHR load

//    DMA0->TCD[0].CITER_ELINKNO=1; //single request
//    DMA0->TCD[0].BITER_ELINKNO=1; //single request


    DMA0->ERQ=DMA_ERQ_ERQ0(1); //enable hardware request
    /* disable auto close request */
    DMA0->TCD[0].CSR &=~DMA_CSR_DREQ(1);
    DMA0->EEI=DMA_EEI_EEI0(1);//enable interrupt

void ini_pit(){
    pit_config_t pit_conf;
    uint32_t freq = CLOCK_GetBusClkFreq();

    PIT_SetTimerPeriod(PIT, kPIT_Chnl_0,freq/1000000 ); //1M freq

    PIT_Init(PIT, &pit_conf);
    PIT_StartTimer(PIT, kPIT_Chnl_0);

Tags (4)
3 Replies

Contributor IV

I've figured out what causes the problem - TFFF flag after DMA transfers not set up again or wrong time.

So if I set it through debug session - immediately I see next value in the PUSHR(and DAC respectively). But after single transaction TFFF flag goes zero.

 My SPI inicialization code is the following:

void spi1_ini(){
    dspi_master_config_t config;
    dspi_master_config_t*    spi1_config = &config;
    dspi_master_ctar_config_t ctar;




//    GPIO_PinWrite(GPIOE, DAC_EN, 0); //disables DAC
    GPIO_PinWrite(GPIOE, DAC_EN, 1); //enables DAC
    SIM->SCGC6|= SIM_SCGC6_SPI1(1);
    DSPI_MasterInit(SPI1_BASE, spi1_config, 48000000);
    SPI1->MCR|= SPI_MCR_FRZ(1);
    SPI1->RSER|=SPI_RSER_TFFF_DIRS(1)|SPI_RSER_TFFF_RE(1);//dma request enable
    DSPI_Enable(SPI1, true);
    DSPI_MasterWriteData(SPI1, &transfer_cmd, DSPI_DUMMY_DATA);

0 Kudos

NXP TechSupport
NXP TechSupport

Hello alexeyusoltsev‌,

Looking at your code I think this is due to you're only setting for 1 cycle so after each transmission you need to start again the transmission. I will suggest checking the example dspi_half_duplex_edma_master and the edma_scatter_gather from the SDK (check the link here).

Let me know if this helps you.

Best Regards,

Alexis Andalon

Contributor IV

  Hi Alexis Andalon,

thanks a lot for your response. I have no processor time to make a 1Mhz interrupt in scatter-gather mode. So I involved channel linking in a way of self-linking.

 But the problem for now is(OMG) that SPI _SR TFFF(FIFO is ready to accept data) flag only sets while TCF flag is cleared, so to start transaction i have to write to TCF of SPI 1 after each transaction to clear TCF manually. If SPI _SR TFFF is not setten up there is no DMA hardware request. I have tried to solve that problem by another channel linking(2DMA channel to send data to 1 SPI) but SPI_SR has fields that protected from writing so I got a bus error. If you know how to solve that i will appreciate it a lot.

 From my point of view SPI in kinetis is not made to work with DMA gluelessly.



0 Kudos