2009-10-27 14:04:49     [BF537] How to use dma in large descriptor list ?

Document created by Aaronwu Employee on Aug 19, 2013
Version 1Show Document
  • View in full screen mode

2009-10-27 14:04:49     [BF537] How to use dma in large descriptor list ?


Message: 81791   




I'am trying to setup a DMA configuration to get data from a multi-channel SPI CAN.


My first configuration was like that :


spi_buffer = (unsigned long)dma_alloc_coherent (NULL, SIZE_64K, &dma_handle, GFP_KERNEL);


set_dma_callback (CH_SPI, spi_dma_callback, NULL);

set_dma_start_addr (CH_SPI, (unsigned long)spi_buffer);

set_dma_x_count (CH_SPI, x_count);

set_dma_x_modify (CH_SPI, x_modify);

set_dma_y_count (CH_SPI, y_count);

set_dma_y_modify (CH_SPI, y_modify);

set_dma_config (CH_SPI, WNR | RESTART | DI_EN | DMAFLOW_AUTO | WDSIZE_16 | DMA2D);


enable_dma (CH_SPI);

set_spi_reg (SPI_CTL,  BIT_CTL_ENABLE | get_spi_reg (SPI_CTL));


it's work fine !


My problem is in mode Flow Auto, some time some value are erased by the next value in the buffer (circular buffer), because of latence in poll system, read, .. and other linux stuff.


So i want to configuration the DMA to use 2 buffers and swap between them, to keep data in a safe buffer.


I think, i must use the large descriptor flow mode (not small because buffer are 64K)


struct dmasg dma_sg[2];

dma_sg[0].next_desc_addr = (unsigned long)&dma_sg[1];

dma_sg[1].next_desc_addr = (unsigned long)&dma_sg[0];

dma_sg[0].start_addr = buffer_A_64K;

dma_sg[1].start_addr = buffer_B_64K;

dma_sg[1].x_count     = dma_sg[0].x_count;

dma_sg[1].x_modify     = dma_sg[0].x_modify;

dma_sg[1].y_count     = dma_sg[0].y_count;

dma_sg[1].y_modify     = dma_sg[0].y_modify;


and about the config register ?


dma_sg[0].cfg = WNR | RESTART | DI_EN | DMAFLOW_LARGE | NDSIZE_2 | WDSIZE_16 | DMA2D;     // maybe ??

dma_sg[1].cfg = ??????


and finaly ?


set_dma_sg (CH_SPI, dma_sg, 2);


enable_dma (CH_SPI);

set_spi_reg (SPI_CTL,  BIT_CTL_ENABLE | get_spi_reg (SPI_CTL));




How to configure my second sg.cfg ?

When the interrupt will be arrive? at end of the 2 sg, or at end of each sg ?

And what about the restart in this mode, for continious acquisition ?


I have read doc and hardware reference, but it's not so clear for me;


i work with the 2008R1.5-RC3 and a Linux toolchain


Thanks for all,


William MARTIN